Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event wip #294

Open
wants to merge 22 commits into
base: trunk
Choose a base branch
from
Open

Event wip #294

wants to merge 22 commits into from

Conversation

ylavic
Copy link
Member

@ylavic ylavic commented Feb 4, 2022

mpm_event changes/improvements for async, debugging and pass pytests (see each commit's message).

First commits are cherry-picked from @minfrin's work (also in https://github.com/apache/httpd/tree/trunk-ssl-handshake-nonblocking)

@ylavic ylavic mentioned this pull request Feb 4, 2022
@ylavic ylavic force-pushed the event_wip branch 10 times, most recently from 5baba5b to a3f2d7f Compare February 9, 2022 00:21
asfgit pushed a commit that referenced this pull request Feb 9, 2022
@ylavic ylavic force-pushed the event_wip branch 6 times, most recently from 1112038 to e4153c1 Compare February 9, 2022 16:56
asfgit pushed a commit that referenced this pull request Feb 9, 2022
@ylavic ylavic force-pushed the event_wip branch 2 times, most recently from 892b871 to ec100d6 Compare February 11, 2022 02:42
@ylavic ylavic force-pushed the event_wip branch 4 times, most recently from df3814b to c25cf0a Compare March 24, 2022 01:49
@ylavic ylavic force-pushed the event_wip branch 3 times, most recently from d912268 to 57d5dc6 Compare April 5, 2022 18:13
@ylavic ylavic force-pushed the event_wip branch 7 times, most recently from fe4ea27 to f5d3256 Compare July 11, 2024 13:37
ylavic added 22 commits July 11, 2024 17:04
Rename the ap_filter_input_pending() and ap_filter_output_pending() core
hooks to ap_core_input_pending() and ap_core_output_pending() respectively.
Change them to return AGAIN when some data are pending.

Add ap_check_input_pending() and ap_check_output_pending() to run the hooks and
fix the return value (DECLINED -> OK, c->aborted -> DONE).

Adapt the callers to the new API (DECLINED -> OK, OK -> AGAIN, DONE).
If clock_gettime() and CLOCK_MONOTONIC are defined (i.e. most/all?  unixes),
use them to provide a timestamp that never goes past (even if the admin
changes the system time). This avoids entries potentially suddenly expiring
in centuries on a bad clock skew.

* configure.in():
  Provide HAVE_TIME_H, HAVE_CLOCK_GETTIME and HAVE_CLOCK_GETRES.

* server/mpm/event/event.c(event_time_now):
  New helper to get a monotonic timestamp from clock_gettime() if it's
  available, or apr_time_now() (i.e. gettimeofday()) otherwise.

* server/mpm/event/event.c(process_socket, event_resume_suspended,
                           event_get_timer_event, process_lingering_close,
                           listener_thread, event_run):
  Use event_time_now().
Regardless of keep_alive_timeout_set which anyway is only about the
KeepAliveTimeout to apply _after_ the current request, always use the
request's server Timeout during its processing (i.e. CONN_STATE_HEAR
and CONN_STATE_COMPLETION).

To save the next KeepAliveTimeout to use later, add a new event_srv_cfg
to the conn_state which points to the appropriate server (either r->server
or c->base_server depending on keep_alive_timeout_set as before).

* server/mpm/event/event.c(struct event_conn_state_t):
  Add event_srv_cfg *ka_sc as the server config to apply for kept alive
  connections.

* server/mpm/event/event.c(event_post_read_request):
  Always set cs->sc to the event_srv_cfg or the request's server, and
  point cs->ka_sc to the appropriate one according to keep_alive_timeout_set.

* server/mpm/event/event.c(make_conn_state):
  Initialize cs->ka_sc to the ap_server_conf's event_srv_cfg, like cs->sc.

* server/mpm/event/event.c(process_socket):
  Use cs->ka_sc->ka_q for CONN_STATE_KEEPALIVE.
Provide a new min_connection_timeout hook that modules enforcing a
dynamic connection timeout (e.g. mod_reqtimeout) should use to inform
ap_get_connection_timeout() users about the current timeout being
applied.

Expose the current timeout enforced by mod_reqtimeout by implementing
the min_connection_timeout hook.

* include/ap_mmn.h():
  Minor bump for min_connection_timeout and ap_get_connection_timeout().

* include/http_connection.h():
  Declare min_connection_timeout and ap_get_connection_timeout().

* server/connection.c():
  Implement min_connection_timeout and ap_get_connection_timeout().

* modules/filters/mod_reqtimeout.c(struct reqtimeout_stage_t):
  Add server_timeout as the timeout defined for the server at the current
  stage.

* modules/filters/mod_reqtimeout.c(struct reqtimeout_con_cfg):
  Add time_left as the dynamic timeout enforced by mod_reqtimeout at the
  current stage.

* modules/filters/mod_reqtimeout.c(check_time_left):
  Store the computed time_left in the reqtimeout_con_cfg, and set the
  socket timeout there (returning an error which will be caught if that
  fails).

* modules/filters/mod_reqtimeout.c(extend_timeout):
  Update time_left in the reqtimeout_con_cfg per the time taken by the last
  read.

* modules/filters/mod_reqtimeout.c(reqtimeout_filter):
  Remove the special path for APR_NONBLOCK_READ or AP_MODE_EATCRLF, it
  does the exact same thing than the !(AP_MODE_GETLINE && APR_BLOCK_READ)
  one.

* modules/filters/mod_reqtimeout.c(reqtimeout_init, reqtimeout_before_header,
                                   reqtimeout_before_body, INIT_STAGE):
  Set the server_timeout in the current stage.

* modules/filters/mod_reqtimeout.c(reqtimeout_min_timeout):
  The new hook implementation.
If ap_run_process_connection() returns CONN_STATE_ASYNC_WAITIO and the
connection timeout as returned by ap_get_connection_timeout() is different
than the waitio_q timeout, use a timer event rather than the waitio_q to keep
track of the idle connection.

* server/mpm_fdqueue.h(truct timer_event_t):
  Add the "timeout" field to store the timeout of the timer, recomputing
  it from "when" would require to call apr_time_now() otherwise.

* server/mpm/event/event.c():
  #define TIMER_MIN_TIMEOUT as the minimal timer event's timeout, to
  prevent the events from firing before the sockets are added to the
  pollset. Currently set to 50ms (an arbitrary value..).

* server/mpm/event/event.c(struct event_conn_state_t):
  Add the timer_event_t *te field as an alternative to the q.

* server/mpm/event/event.c(struct event_srv_cfg_s):
  Add the server_rec *s field to backref the server_rec and easily pass
  cs->sc->s to ap_get_connection_timeout().

* server/mpm/event/event.c(pollset_add_at, pollset_del_at):
  If the connection is attached to a timer event, log a "t" instead of
  a "q" and the timer's timeout instead of the q's.

* server/mpm/event/event.c(process_socket):
  If ap_get_connection_timeout() is different than the waitio_q timeout,
  acquire a timer event and associate it with the conn_state. A timer
  event associated with a conn_state has a NULL callback (cbfn).

* server/mpm/event/event.c(event_get_timer_event):
  Set the given timeout to the ->timeout field.

* server/mpm/event/event.c(event_register_timed_callback_ex,
                           event_register_poll_callback_ex):
  Return APR_EINVAL if the given callbacks are NULL, this is reserved
  for conn_state timers now. Since it would have crashed at some point
  to pass NULL callbacks before, it's not really an API change.

* server/mpm/event/event.c(listener_thread):
  Fix the poll() timeout set from timers_next_expiry which should be
  taken into account whether it expired or not.
  When a conn_state timer fires/expires, remove it from the pollset and
  abort the connection (with APLOG_INFO).
  When a conn_state timer is polled, cancel the timer.
If AP_MPMQ_CAN_WAITIO, make mod_ssl perform non blocking TLS handshakes and
go async when it would block.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant