Skip to content

Commit fe4ea27

Browse files
committed
mod_proxy,mpm_event: Replace ap_mpm_register_poll_callback*() by ap_mpm_poll_suspended() to avoid races.
1 parent f3ce201 commit fe4ea27

File tree

11 files changed

+607
-514
lines changed

11 files changed

+607
-514
lines changed

include/ap_mmn.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -735,14 +735,18 @@
735735
* ap_check_output_pending()
736736
* 20211221.27 (2.5.1-dev) Add min_connection_timeout hook and
737737
* ap_get_connection_timeout()
738+
* 20211221.28 (2.5.1-dev) Add ap_mpm_poll_suspended() and
739+
* AP_MPMQ_CAN_POLL_SUSPENDED
740+
* 20240701.0 (2.5.1-dev) Axe ap_mpm_register_poll_callback and
741+
* ap_mpm_register_poll_callback_timeout
738742
*/
739743

740744
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
741745

742746
#ifndef MODULE_MAGIC_NUMBER_MAJOR
743-
#define MODULE_MAGIC_NUMBER_MAJOR 20211221
747+
#define MODULE_MAGIC_NUMBER_MAJOR 20240701
744748
#endif
745-
#define MODULE_MAGIC_NUMBER_MINOR 27 /* 0...n */
749+
#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
746750

747751
/**
748752
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a

include/ap_mpm.h

+6-45
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process(
184184
#define AP_MPMQ_CAN_POLL 18
185185
/** MPM supports CONN_STATE_ASYNC_WAITIO */
186186
#define AP_MPMQ_CAN_WAITIO 19
187+
/** MPM implements the poll_suspended hook */
188+
#define AP_MPMQ_CAN_POLL_SUSPENDED 20
187189
/** @} */
188190

189191
/**
@@ -206,54 +208,13 @@ typedef void (ap_mpm_callback_fn_t)(void *baton);
206208
/* only added support in the Event MPM.... check for APR_ENOTIMPL */
207209
AP_DECLARE(apr_status_t) ap_mpm_resume_suspended(conn_rec *c);
208210
/* only added support in the Event MPM.... check for APR_ENOTIMPL */
211+
AP_DECLARE(apr_status_t) ap_mpm_poll_suspended(conn_rec *c, apr_pool_t *p,
212+
const apr_array_header_t *pfds,
213+
apr_interval_time_t timeout);
214+
/* only added support in the Event MPM.... check for APR_ENOTIMPL */
209215
AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(
210216
apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton);
211217

212-
/**
213-
* Register a callback on the readability or writability on a group of
214-
* sockets/pipes.
215-
* @param p Pool used by the MPM for its internal allocations
216-
* @param pfds Array of apr_pollfd_t
217-
* @param cbfn The callback function
218-
* @param baton userdata for the callback function
219-
* @return APR_SUCCESS if all sockets/pipes could be added to a pollset,
220-
* APR_ENOTIMPL if no asynch support, or an apr_pollset_add error.
221-
* @remark When activity is found on any 1 socket/pipe in the list, all are removed
222-
* from the pollset and only 1 callback is issued.
223-
* @remark The passed in pool can be cleared by cbfn and tofn when called back,
224-
* it retains no MPM persistent data and won't be used until the next call
225-
* to ap_mpm_register_poll_callback[_timeout].
226-
*/
227-
228-
AP_DECLARE(apr_status_t) ap_mpm_register_poll_callback(
229-
apr_pool_t *p, const apr_array_header_t *pfds,
230-
ap_mpm_callback_fn_t *cbfn, void *baton);
231-
232-
/**
233-
* Register a callback on the readability or writability on a group of sockets/pipes,
234-
* with a timeout.
235-
* @param p Pool used by the MPM for its internal allocations
236-
* @param pfds Array of apr_pollfd_t
237-
* @param cbfn The callback function
238-
* @param tofn The callback function if the timeout expires
239-
* @param baton userdata for the callback function
240-
* @param timeout timeout for I/O in microseconds, unlimited if <= 0
241-
* @return APR_SUCCESS if all sockets/pipes could be added to a pollset,
242-
* APR_ENOTIMPL if no asynch support, or an apr_pollset_add error.
243-
* @remark When activity is found on any 1 socket/pipe in the list, all are removed
244-
* from the pollset and only 1 callback is issued.
245-
* @remark For each call, only one of tofn or cbfn will be called, never both.
246-
* @remark The passed in pool can be cleared by cbfn and tofn when called back,
247-
* it retains no MPM persistent data and won't be used until the next call
248-
* to ap_mpm_register_poll_callback[_timeout].
249-
*/
250-
251-
AP_DECLARE(apr_status_t) ap_mpm_register_poll_callback_timeout(
252-
apr_pool_t *p, const apr_array_header_t *pfds,
253-
ap_mpm_callback_fn_t *cbfn, ap_mpm_callback_fn_t *tofn,
254-
void *baton, apr_time_t timeout);
255-
256-
257218
typedef enum mpm_child_status {
258219
MPM_CHILD_STARTED,
259220
MPM_CHILD_EXITED,

include/httpd.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ typedef enum {
13341334
CONN_STATE_PROCESSING, /* Processed by process_connection hooks */
13351335
CONN_STATE_HANDLER, /* Processed by the modules handlers */
13361336
CONN_STATE_WRITE_COMPLETION, /* Flushed by the MPM before entering CONN_STATE_KEEPALIVE */
1337-
CONN_STATE_SUSPENDED, /* Suspended in the MPM until ap_run_resume_suspended() */
1337+
CONN_STATE_SUSPENDED, /* Suspended from the MPM until ap_run_resume_suspended() */
13381338
CONN_STATE_LINGER, /* MPM flushes then closes the connection with lingering */
13391339
CONN_STATE_LINGER_NORMAL, /* MPM has started lingering close with normal timeout */
13401340
CONN_STATE_LINGER_SHORT, /* MPM has started lingering close with short timeout */

include/mpm_common.h

+4-14
Original file line numberDiff line numberDiff line change
@@ -422,22 +422,12 @@ AP_DECLARE_HOOK(int, mpm_query, (int query_code, int *result, apr_status_t *rv))
422422
AP_DECLARE_HOOK(apr_status_t, mpm_register_timed_callback,
423423
(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton))
424424

425-
/**
426-
* register the specified callback
427-
* @ingroup hooks
428-
*/
429-
AP_DECLARE_HOOK(apr_status_t, mpm_register_poll_callback,
430-
(apr_pool_t *p, const apr_array_header_t *pds,
431-
ap_mpm_callback_fn_t *cbfn, void *baton))
432-
433-
/* register the specified callback, with timeout
425+
/** Put suspended connection's pollfds into the MPM's pollset
434426
* @ingroup hooks
435-
*
436427
*/
437-
AP_DECLARE_HOOK(apr_status_t, mpm_register_poll_callback_timeout,
438-
(apr_pool_t *p, const apr_array_header_t *pds,
439-
ap_mpm_callback_fn_t *cbfn, ap_mpm_callback_fn_t *tofn,
440-
void *baton, apr_time_t timeout))
428+
AP_DECLARE_HOOK(apr_status_t, mpm_poll_suspended,
429+
(conn_rec *c, apr_pool_t *p, const apr_array_header_t *pfds,
430+
apr_interval_time_t timeout))
441431

442432
/** Resume the suspended connection
443433
* @ingroup hooks

modules/http/http_core.c

+11-9
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,22 @@ static int ap_process_http_async_connection(conn_rec *c)
182182
* of nondeterministic failures later.
183183
*/
184184
r = NULL;
185-
}
186185

187-
if (cs->state != CONN_STATE_WRITE_COMPLETION &&
188-
cs->state != CONN_STATE_SUSPENDED &&
189-
cs->state != CONN_STATE_LINGER) {
190-
/* Something went wrong; close the connection */
191-
cs->state = CONN_STATE_LINGER;
186+
switch (cs->state) {
187+
case CONN_STATE_WRITE_COMPLETION:
188+
case CONN_STATE_SUSPENDED:
189+
case CONN_STATE_LINGER:
190+
return OK;
191+
default:
192+
/* Unexpected, close */
193+
break;
194+
}
192195
}
193196
}
194-
else { /* ap_read_request failed - client may have closed */
195-
cs->state = CONN_STATE_LINGER;
196-
}
197197
}
198198

199+
/* Something went wrong; close the connection */
200+
cs->state = CONN_STATE_LINGER;
199201
return OK;
200202
}
201203

0 commit comments

Comments
 (0)