On Mon, Jan 23, 2012 at 09:39:38PM +0100, Stefan Fritsch wrote: > This patch allows us to later add members to core_ctx_t without > breaking binary compatibility to mod_ftp. Without such a patch, the > size of core_ctx_t is part of the ABI, which is bad. > > Opinions?
After thinking about it more: the WinNT MPM use of this facility still seems unnecessary. The same effect could be achieved using an input filter which returns the extra data from AcceptEx. Here's a proof of concept for prefork, which prepends "GET" to data received from the socket - no core hacks required. (This is dumb and should be more sophisticated, it would need to handle AP_MODE_GETBYTES/AP_MODE_GETLINE if possible from the "extra" data alone, without always fetching a brigade from the socket) For mod_ftp the need to replace the socket bucket looks more convincing, but still surely a hook calling *out* from the core is better? AP_DECLARE_HOOK(int, insert_network_bucket, (connection_conn *c, apr_bucket_brigade *bb, apr_socket_t *socket)); then core i.f. does net->in_ctx = ctx = ap_create_core_ctx(f->c); ap_run_insert_network_bucket(c, ctx->b, net->client_socket); and mod_ftp can insert its polling data bucket there instead? (I haven't thought this one through, I admit, handwaving may be required) Index: server/mpm/prefork/prefork.c =================================================================== --- server/mpm/prefork/prefork.c (revision 1235252) +++ server/mpm/prefork/prefork.c (working copy) @@ -95,6 +95,8 @@ static int mpm_state = AP_MPMQ_STARTING; static ap_pod_t *pod; +static ap_filter_rec_t *prefork_filter_handle; + /* data retained by prefork across load/unload of the module * allocated on first call to pre-config hook; located on * subsequent calls to pre-config hook @@ -468,6 +470,23 @@ #endif } +static apr_status_t prefork_filter(ap_filter_t *f, apr_bucket_brigade *bb, + ap_input_mode_t mode, apr_read_type_e block, + apr_off_t bytes) +{ + apr_status_t rv; + const char *string = f->ctx; + + rv = ap_get_brigade(f->next, bb, mode, block, bytes); + if (rv == APR_SUCCESS && string) { + apr_bucket *e = apr_bucket_immortal_create(string, strlen(string), f->c->bucket_alloc); + APR_BRIGADE_INSERT_HEAD(bb, e); + f->ctx = NULL; + } + + return rv; +} + /***************************************************************** * Child process main loop. * The following vars are static to avoid getting clobbered by longjmp(); @@ -691,6 +710,10 @@ current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc); if (current_conn) { + + ap_add_input_filter_handle(prefork_filter_handle, "GET", + NULL, current_conn); + #if APR_HAS_THREADS current_conn->current_thread = thd; #endif @@ -1454,6 +1477,10 @@ ap_hook_mpm(prefork_run, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_mpm_query(prefork_query, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_mpm_get_name(prefork_get_name, NULL, NULL, APR_HOOK_MIDDLE); + + prefork_filter_handle = + ap_register_input_filter("PREFORK", prefork_filter, NULL, + AP_FTYPE_NETWORK - 1); } static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)