Now that the input and output brigades are only operated on from a single thread, the extra pool and bucket allocator added as part of commit cfaef071 can be removed. Also, allocate a single long-lived input brigade instead of allocating new ones for every socket read. --- mod_websocket.c | 49 ++++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 31 deletions(-)
diff --git a/mod_websocket.c b/mod_websocket.c index 8e3bf26..9c62ca5 100644 --- a/mod_websocket.c +++ b/mod_websocket.c @@ -465,21 +465,19 @@ static void CALLBACK mod_websocket_plugin_close(const WebSocketServer * /* * Read a buffer of data from the input stream. */ -static apr_status_t mod_websocket_read_nonblock(request_rec *r, char *buffer, +static apr_status_t mod_websocket_read_nonblock(request_rec *r, + apr_bucket_brigade *bb, + char *buffer, apr_size_t *bufsiz) { - apr_status_t rv = APR_ENOMEM; - apr_bucket_brigade *bb; + apr_status_t rv; - bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); - if (bb != NULL) { - if ((rv = - ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, - APR_NONBLOCK_READ, *bufsiz)) == APR_SUCCESS) { - rv = apr_brigade_flatten(bb, buffer, bufsiz); - } - apr_brigade_destroy(bb); + if ((rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, + APR_NONBLOCK_READ, *bufsiz)) == APR_SUCCESS) { + rv = apr_brigade_flatten(bb, buffer, bufsiz); + apr_brigade_cleanup(bb); } + return rv; } @@ -893,29 +891,17 @@ static void mod_websocket_data_framing(const WebSocketServer *server, { WebSocketState *state = server->state; request_rec *r = state->r; - apr_pool_t *pool = NULL; - apr_bucket_alloc_t *bucket_alloc; - apr_bucket_brigade *obb; + apr_bucket_brigade *ibb, *obb; apr_pollset_t *pollset; apr_pollfd_t pollfd = { 0 }; const apr_pollfd_t *signalled; apr_int32_t pollcnt; apr_queue_t * queue; - /* We cannot use the same bucket allocator for the ouput bucket brigade - * obb as the one associated with the connection (r->connection->bucket_alloc) - * because the same bucket allocator cannot be used in two different - * threads, and we use the connection bucket allocator in this - * thread - see docs on apr_bucket_alloc_create(). This results in - * occasional core dumps. So create our own bucket allocator and pool - * for output thread bucket brigade. (Thanks to Alex Bligh -- abligh) - */ - - if ((apr_pool_create(&pool, r->pool) == APR_SUCCESS) && - ((bucket_alloc = apr_bucket_alloc_create(pool)) != NULL) && - ((obb = apr_brigade_create(pool, bucket_alloc)) != NULL) && - (apr_pollset_create(&pollset, 1, pool, APR_POLLSET_WAKEABLE) == APR_SUCCESS) && - (apr_queue_create(&queue, QUEUE_CAPACITY, pool) == APR_SUCCESS)) { + if (((ibb = apr_brigade_create(r->pool, r->connection->bucket_alloc)) != NULL) && + ((obb = apr_brigade_create(r->pool, r->connection->bucket_alloc)) != NULL) && + (apr_pollset_create(&pollset, 1, r->pool, APR_POLLSET_WAKEABLE) == APR_SUCCESS) && + (apr_queue_create(&queue, QUEUE_CAPACITY, r->pool) == APR_SUCCESS)) { unsigned char block[BLOCK_DATA_SIZE]; apr_int64_t block_size; unsigned char status_code_buffer[2]; @@ -935,7 +921,7 @@ static void mod_websocket_data_framing(const WebSocketServer *server, state->queue = queue; /* Initialize the pollset */ - pollfd.p = pool; + pollfd.p = r->pool; pollfd.desc_type = APR_POLL_SOCKET; pollfd.reqevents = APR_POLLIN; pollfd.desc.s = ap_get_conn_socket(state->r->connection); @@ -960,7 +946,7 @@ static void mod_websocket_data_framing(const WebSocketServer *server, /* Check to see if there is any data to read. */ block_size = sizeof(block); - rv = mod_websocket_read_nonblock(r, (char *)block, &block_size); + rv = mod_websocket_read_nonblock(r, ibb, (char *)block, &block_size); if (rv == APR_SUCCESS) { mod_websocket_handle_incoming(server, block, block_size, @@ -1026,8 +1012,9 @@ static void mod_websocket_data_framing(const WebSocketServer *server, status_code_buffer, sizeof(status_code_buffer)); - /* We are done with the bucket brigade */ + /* We are done with the bucket brigades */ state->obb = NULL; + apr_brigade_destroy(ibb); apr_brigade_destroy(obb); state->pollset = NULL; -- 2.1.1