On Sat, Jan 27, 2018 at 3:14 PM, Yann Ylavic <[email protected]> wrote:
>
> So I wonder if we'd better:
> 1. have a constant file name (no generation suffix) for all systems,
> 2. not unlink/remove the SHM file on pconf cleanup,
> 2'. eventually unlink the ones unused in ++generation (e.g. retained
> global list),
> 3. unlink all on pglobal cleanup.
>
> Now we'd have a working shm_attach() not only for persisted slotmems,
> while shm_create() would only be called for new SHMs which we know can
> be pre-removed (to work around crashes leaving them registered
> somewhere).
> Also, if attach succeeds on startup (first generation) but the SHM is
> not persisted (an old crash still), we can possibly pass the sizes
> checks and re-create the SHM regardless.
>
> WDYT?
Something like the attached patch (it talks better sometimes...).
Not even tested of course :)
Index: modules/proxy/proxy_util.c
===================================================================
--- modules/proxy/proxy_util.c (revision 1821739)
+++ modules/proxy/proxy_util.c (working copy)
@@ -1370,7 +1370,9 @@ static apr_status_t connection_cleanup(void *theco
}
/* determine if the connection need to be closed */
- if (!worker->s->is_address_reusable || worker->s->disablereuse) {
+ if (!worker->s->is_address_reusable
+ || worker->s->disablereuse
+ || conn->uds_path) {
apr_pool_t *p = conn->pool;
apr_pool_clear(p);
conn = apr_pcalloc(p, sizeof(proxy_conn_rec));
@@ -2295,24 +2297,14 @@ ap_proxy_determine_connection(apr_pool_t *p, reque
* to check host and port on the conn and be careful about
* spilling the cached addr from the worker.
*/
- uds_path = (*worker->s->uds_path ? worker->s->uds_path : apr_table_get(r->notes, "uds_path"));
+ uds_path = *worker->s->uds_path ? worker->s->uds_path
+ : apr_table_get(r->notes, "uds_path");
if (uds_path) {
- if (conn->uds_path == NULL) {
- /* use (*conn)->pool instead of worker->cp->pool to match lifetime */
- conn->uds_path = apr_pstrdup(conn->pool, uds_path);
- }
- if (conn->uds_path) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02545)
- "%s: has determined UDS as %s",
- uri->scheme, conn->uds_path);
- }
- else {
- /* should never happen */
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02546)
- "%s: cannot determine UDS (%s)",
- uri->scheme, uds_path);
-
- }
+ /* use conn->pool instead of worker->cp->pool to match lifetime */
+ conn->uds_path = apr_pstrdup(conn->pool, uds_path);
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02545)
+ "%s: has determined UDS as %s",
+ uri->scheme, conn->uds_path);
/*
* In UDS cases, some structs are NULL. Protect from de-refs
* and provide info for logging at the same time.
@@ -2829,6 +2821,7 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const
break;
}
conn->connection = NULL;
+ conn->close = 1;
rv = ap_proxy_connect_uds(newsock, conn->uds_path, conn->scpool);
if (rv != APR_SUCCESS) {
Index: modules/slotmem/mod_slotmem_shm.c
===================================================================
--- modules/slotmem/mod_slotmem_shm.c (revision 1821739)
+++ modules/slotmem/mod_slotmem_shm.c (working copy)
@@ -47,7 +47,7 @@ struct ap_slotmem_instance_t {
int fbased; /* filebased? */
void *shm; /* ptr to memory segment (apr_shm_t *) */
void *base; /* data set start */
- apr_pool_t *gpool; /* per segment global pool */
+ apr_pool_t *pool; /* per segment working pool */
char *inuse; /* in-use flag table*/
unsigned int *num_free; /* slot free count for this instance */
void *persist; /* persist dataset start */
@@ -64,7 +64,8 @@ struct ap_slotmem_instance_t {
*/
/* global pool and list of slotmem we are handling */
-static struct ap_slotmem_instance_t *globallistmem = NULL;
+static struct ap_slotmem_instance_t *globallistmem = NULL,
+ **retained_globallistmem = NULL;
static apr_pool_t *gpool = NULL;
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
@@ -191,11 +192,11 @@ static void store_slotmem(ap_slotmem_instance_t *s
if (storename) {
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
- APR_OS_DEFAULT, slotmem->gpool);
+ APR_OS_DEFAULT, slotmem->pool);
if (APR_STATUS_IS_EEXIST(rv)) {
- apr_file_remove(storename, slotmem->gpool);
+ apr_file_remove(storename, slotmem->pool);
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
- APR_OS_DEFAULT, slotmem->gpool);
+ APR_OS_DEFAULT, slotmem->pool);
}
if (rv != APR_SUCCESS) {
return;
@@ -212,7 +213,7 @@ static void store_slotmem(ap_slotmem_instance_t *s
}
apr_file_close(fp);
if (rv != APR_SUCCESS) {
- apr_file_remove(storename, slotmem->gpool);
+ apr_file_remove(storename, slotmem->pool);
}
}
}
@@ -271,26 +272,35 @@ static apr_status_t restore_slotmem(void *ptr, con
return rv;
}
+static apr_status_t global_cleanup_slotmem(void *param)
+{
+ AP_DEBUG_ASSERT(retained_globallistmem != NULL);
+ *retained_globallistmem = NULL;
+
+ while (globallistmem) {
+ if (globallistmem->fbased) {
+ apr_shm_destroy(globallistmem->shm);
+ apr_shm_remove(globallistmem->name, globallistmem->pool);
+ apr_file_remove(globallistmem->name, globallistmem->pool);
+ }
+ globallistmem = globallistmem->next;
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t cleanup_slotmem(void *param)
{
- ap_slotmem_instance_t **mem = param;
+ AP_DEBUG_ASSERT(retained_globallistmem != NULL);
+ *retained_globallistmem = globallistmem;
- if (*mem) {
- ap_slotmem_instance_t *next = *mem;
- while (next) {
- if (AP_SLOTMEM_IS_PERSIST(next)) {
- store_slotmem(next);
- }
- apr_shm_destroy((apr_shm_t *)next->shm);
- if (next->fbased) {
- apr_shm_remove(next->name, next->gpool);
- apr_file_remove(next->name, next->gpool);
- }
- next = next->next;
+ while (globallistmem) {
+ if (AP_SLOTMEM_IS_PERSIST(globallistmem)) {
+ store_slotmem(globallistmem);
}
+ globallistmem = globallistmem->next;
}
- /* apr_pool_destroy(gpool); */
- globallistmem = NULL;
+
return APR_SUCCESS;
}
@@ -338,11 +348,11 @@ static apr_status_t slotmem_create(ap_slotmem_inst
apr_size_t size = AP_SLOTMEM_OFFSET + AP_UNSIGNEDINT_OFFSET +
(item_num * sizeof(char)) + basesize;
int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
+ int generation = 0;
apr_status_t rv;
- if (gpool == NULL) {
- return APR_ENOSHMAVAIL;
- }
+ ap_mpm_query(AP_MPMQ_GENERATION, &generation);
+
if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
/* first try to attach to existing slotmem */
if (next) {
@@ -372,13 +382,13 @@ static apr_status_t slotmem_create(ap_slotmem_inst
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300)
"create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size,
item_num);
- if (fbased) {
- rv = apr_shm_attach(&shm, fname, gpool);
+ if (fbased && generation > 1) {
+ rv = apr_shm_attach(&shm, fname, pool);
}
else {
rv = APR_EINVAL;
}
- if (rv == APR_SUCCESS) {
+ if (rv == APR_SUCCESS && persist) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598)
"apr_shm_attach() succeeded");
@@ -401,10 +411,10 @@ static apr_status_t slotmem_create(ap_slotmem_inst
}
ptr += AP_SLOTMEM_OFFSET;
}
- else {
+ else if (rv != APR_SUCCESS) {
apr_size_t dsize = size - AP_SLOTMEM_OFFSET;
if (fbased) {
- apr_shm_remove(fname, gpool);
+ apr_shm_remove(fname, pool);
rv = apr_shm_create(&shm, size, fname, gpool);
}
else {
@@ -444,8 +454,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst
}
/* For the chained slotmem stuff */
- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
- sizeof(ap_slotmem_instance_t));
+ res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
res->name = apr_pstrdup(gpool, fname);
res->pname = apr_pstrdup(gpool, pname);
res->fbased = fbased;
@@ -458,7 +467,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst
ptr += AP_UNSIGNEDINT_OFFSET;
res->base = (void *)ptr;
res->desc = desc;
- res->gpool = gpool;
+ res->pool = pool;
res->next = NULL;
res->inuse = ptr + basesize;
if (globallistmem == NULL) {
@@ -485,9 +494,6 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
apr_shm_t *shm;
apr_status_t rv;
- if (gpool == NULL) {
- return APR_ENOSHMAVAIL;
- }
if (!slotmem_filenames(pool, name, &fname, NULL)) {
return APR_ENOSHMAVAIL;
}
@@ -528,8 +534,7 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
ptr += AP_SLOTMEM_OFFSET;
/* For the chained slotmem stuff */
- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
- sizeof(ap_slotmem_instance_t));
+ res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
res->name = apr_pstrdup(gpool, fname);
res->fbased = 1;
res->shm = shm;
@@ -538,7 +543,7 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
ptr += AP_UNSIGNEDINT_OFFSET;
res->base = (void *)ptr;
res->desc = desc;
- res->gpool = gpool;
+ res->pool = pool;
res->inuse = ptr + (desc.size * desc.num);
res->next = NULL;
if (globallistmem == NULL) {
@@ -760,18 +765,23 @@ static const ap_slotmem_provider_t *slotmem_shm_ge
}
/* initialise the global pool */
-static void slotmem_shm_initgpool(apr_pool_t *p)
+static int pre_config(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp)
{
- gpool = p;
+ const char *retained_key = "mod_slotmem_shm";
+ retained_globallistmem = ap_retained_data_get(retained_key);
+ if (!retained_globallistmem) {
+ retained_globallistmem =
+ ap_retained_data_create(retained_key,
+ sizeof *retained_globallistmem);
+ apr_pool_cleanup_register(ap_pglobal, NULL, global_cleanup_slotmem,
+ apr_pool_cleanup_null);
+ }
+ globallistmem = *retained_globallistmem;
+ gpool = ap_pglobal;
+ return OK;
}
-/* Add the pool_clean routine */
-static void slotmem_shm_initialize_cleanup(apr_pool_t *p)
-{
- apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem,
- apr_pool_cleanup_null);
-}
-
/*
* Make sure the shared memory is cleaned
*/
@@ -778,17 +788,11 @@ static const ap_slotmem_provider_t *slotmem_shm_ge
static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *s)
{
- slotmem_shm_initialize_cleanup(p);
+ apr_pool_cleanup_register(p, NULL, cleanup_slotmem,
+ apr_pool_cleanup_null);
return OK;
}
-static int pre_config(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp)
-{
- slotmem_shm_initgpool(p);
- return OK;
-}
-
static void ap_slotmem_shm_register_hook(apr_pool_t *p)
{
const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
Index: server/protocol.c
===================================================================
--- server/protocol.c (revision 1821739)
+++ server/protocol.c (working copy)
@@ -225,6 +225,11 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
int fold = flags & AP_GETLINE_FOLD;
int crlf = flags & AP_GETLINE_CRLF;
+ if (!n) {
+ /* Can't work since we always nul terminate */
+ return APR_ENOSPC;
+ }
+
/*
* Initialize last_char as otherwise a random value will be compared
* against APR_ASCII_LF at the end of the loop if bb only contains
@@ -238,7 +243,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_GETLINE,
APR_BLOCK_READ, 0);
if (rv != APR_SUCCESS) {
- return rv;
+ goto cleanup;
}
/* Something horribly wrong happened. Someone didn't block!
@@ -245,7 +250,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
* (this also happens at the end of each keepalive connection)
*/
if (APR_BRIGADE_EMPTY(bb)) {
- return APR_EGENERAL;
+ rv = APR_EGENERAL;
+ goto cleanup;
}
for (e = APR_BRIGADE_FIRST(bb);
@@ -263,7 +269,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
if (rv != APR_SUCCESS) {
- return rv;
+ goto cleanup;
}
if (len == 0) {
@@ -276,17 +282,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
/* Would this overrun our buffer? If so, we'll die. */
if (n < bytes_handled + len) {
- *read = bytes_handled;
- if (*s) {
- /* ensure this string is NUL terminated */
- if (bytes_handled > 0) {
- (*s)[bytes_handled-1] = '\0';
- }
- else {
- (*s)[0] = '\0';
- }
- }
- return APR_ENOSPC;
+ rv = APR_ENOSPC;
+ goto cleanup;
}
/* Do we have to handle the allocation ourselves? */
@@ -329,19 +326,15 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
}
}
- if (crlf && (last_char <= *s || last_char[-1] != APR_ASCII_CR)) {
- *last_char = '\0';
- bytes_handled = last_char - *s;
- *read = bytes_handled;
- return APR_EINVAL;
- }
-
/* Now NUL-terminate the string at the end of the line;
* if the last-but-one character is a CR, terminate there */
if (last_char > *s && last_char[-1] == APR_ASCII_CR) {
last_char--;
}
- *last_char = '\0';
+ else if (crlf) {
+ rv = APR_EINVAL;
+ goto cleanup;
+ }
bytes_handled = last_char - *s;
/* If we're folding, we have more work to do.
@@ -361,7 +354,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
rv = ap_get_brigade(r->proto_input_filters, bb, AP_MODE_SPECULATIVE,
APR_BLOCK_READ, 1);
if (rv != APR_SUCCESS) {
- return rv;
+ goto cleanup;
}
if (APR_BRIGADE_EMPTY(bb)) {
@@ -378,7 +371,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
if (rv != APR_SUCCESS) {
apr_brigade_cleanup(bb);
- return rv;
+ goto cleanup;
}
/* Found one, so call ourselves again to get the next line.
@@ -395,10 +388,8 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
if (c == APR_ASCII_BLANK || c == APR_ASCII_TAB) {
/* Do we have enough space? We may be full now. */
if (bytes_handled >= n) {
- *read = n;
- /* ensure this string is terminated */
- (*s)[n-1] = '\0';
- return APR_ENOSPC;
+ rv = APR_ENOSPC;
+ goto cleanup;
}
else {
apr_size_t next_size, next_len;
@@ -411,7 +402,6 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
tmp = NULL;
}
else {
- /* We're null terminated. */
tmp = last_char;
}
@@ -420,7 +410,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
rv = ap_rgetline_core(&tmp, next_size,
&next_len, r, 0, bb);
if (rv != APR_SUCCESS) {
- return rv;
+ goto cleanup;
}
if (do_alloc && next_len > 0) {
@@ -434,7 +424,7 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
memcpy(new_buffer, *s, bytes_handled);
/* copy the new line, including the trailing null */
- memcpy(new_buffer + bytes_handled, tmp, next_len + 1);
+ memcpy(new_buffer + bytes_handled, tmp, next_len);
*s = new_buffer;
}
@@ -447,8 +437,21 @@ AP_DECLARE(apr_status_t) ap_rgetline_core(char **s
}
}
}
+
+cleanup:
+ if (bytes_handled >= n) {
+ bytes_handled = n - 1;
+ }
+ if (*s) {
+ /* ensure this string is NUL terminated */
+ (*s)[bytes_handled] = '\0';
+ }
*read = bytes_handled;
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
/* PR#43039: We shouldn't accept NULL bytes within the line */
if (strlen(*s) < bytes_handled) {
return APR_EINVAL;
@@ -487,6 +490,10 @@ AP_DECLARE(int) ap_getline(char *s, int n, request
apr_size_t len;
apr_bucket_brigade *tmp_bb;
+ if (n < 0) {
+ return n;
+ }
+
tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
rv = ap_rgetline(&tmp_s, n, &len, r, flags, tmp_bb);
apr_brigade_destroy(tmp_bb);