Some comments:
@@ -581,6 +564,33 @@
eor_buckets_in_brigade, morphing_bucket_in_brigade);
}
+ /* Handle non blocking writes. If we saw a non blocking bucket, attempt
+ * a non blocking write. If the non blocking write would have returned
+ * APR_EGAIN, set aside the remainder and return APR_EAGAIN.
+ */
+ if (nonblock_bucket_in_brigade) {
+ if (loglevel >= APLOG_TRACE6) {
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE8, APR_SUCCESS, c,
+ "core_output_filter: non blocking write "
+ "to the network");
+ }
+ rv = send_brigade_nonblocking(net->client_socket, bb,
+ &(ctx->bytes_written), c);
+ if (APR_STATUS_IS_EAGAIN(rv)) {
+ setaside_remaining_output(f, ctx, bb, c);
+ }
+ else if (rv != APR_EAGAIN) {
What if rv is APR_SUCCESS?
+ /* The client has aborted the connection */
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE1, rv, c,
+ "core_output_filter: writing data to the network");
+ c->aborted = 1;
+ }
+ return rv;
+ }
+
+ /* Otherwise handle a normal write. A non blocking write will be attempted,
+ * but we don't return APR_EAGAIN, we return APR_SUCCESS instead.
+ */
if (bytes_in_brigade >= THRESHOLD_MIN_WRITE) {
rv = send_brigade_nonblocking(net->client_socket, bb,
&(ctx->bytes_written), c);
+AP_DECLARE_DATA const apr_bucket_type_t ap_bucket_type_nonblock = {
+ "EOC", 5, APR_BUCKET_METADATA,
+ apr_bucket_destroy_noop,
I guess this should be something like "NBB" instead of "EOC" (copy and paste
error?)
Otherwise looks sensible from a brief look.
Regards
Rüdiger
> -----Original Message-----
> From: Graham Leggett
> Sent: Sonntag, 17. November 2013 20:41
> To: [email protected]
> Subject: [Patch] non blocking writes in core
>
> Hi all,
>
> Continuing on from the discussion about how we might support write
> completion in mod_ssl, I have come up with the following patch below.
>
> I started by changing the event MPM to call all protocol filters instead
> of just the hard coded write filter:
>
> rv = ap_pass_brigade(c->output_filters, cs->bb);
>
> The first thing that this revealed was that we need to pass a non-empty
> brigade down the stack. I needed a metadata bucket to pass down the stack
> to make the brigade not-empty, and so chose to create a metadata bucket
> for this purpose (more on this below).
>
> The second thing that we needed to support for mod_ssl to have any hope of
> taking advantage of write completion was non-blocking writes to the core
> output filter. This would give mod_ssl the option to setaside any large
> buckets (example: file buckets) and allow the core to enter write
> completion as soon as it saw EAGAIN.
>
> We can't change the API for ap_pass_brigade() to add a nonblock flag like
> an input filter, but we can pass a NONBLOCK metadata bucket down the
> stack, and this dovetails nicely with our need for a metadata bucket
> above.
>
> So, this patch does the following:
>
> - Takes out the "pass NULL to the core output filter" hack that supported
> write completion previously in the event MPM (other MPMs to follow).
> - Add the nonblock bucket, and pass this bucket down the protocol stack
> during write completion.
> - Teach the core output filter how to react to the NONBLOCK bucket,
> returning APR_EAGAIN appropriately when the NONBLOCK bucket is present
> (and APR_SUCCESS when not, as per previous behaviour).
>
> In theory, this opens the door for us to support asynchronous filters that
> know about NONBLOCK buckets and nonblocking behaviour. In the case of
> naive filters, we may end up with existing blocking behaviour during write
> completion, but this is no worse than we have now.
>
> Also in theory, all of this can be backported to v2.4.
>
> Regards,
> Graham
> --