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)