Author: brane Date: Wed Aug 6 12:02:37 2025 New Revision: 1927641 Log: On the SERF-195 branch: apply the patch from the issue tracker, with some tweaks (no abort() calls in production code, use a static initializer).
* serf_private.h (serf_reqlist_t): New. Linked list of requests. (serf_request_t): Add a member serf_reqlist_t *next. (serf_connection_t): Change the three reqest lists to serf_reqlist_t. (serf__link_requests, serf__req_list_length): Remove prototypes. (serf__push_request, serf__peek_request, serf__take_request, serf__delete_from_reqlist, serf__cancel_request, serf__req_list_recalc_length): New and modified prototypes. * src/outgoing_request.c (SERF__REQLIST_assert): New debug-assert macro. (serf__link_requests): Removed. ((serf__push_request, serf__peek_request, serf__take_request, serf__delete_from_reqlist): New. (serf__cancel_request): Change the 'list' argument type and update. (serf__destroy_request, serf__provide_credentials, create_request, serf_connection_request_create, insert_priority_request, serf_connection__request_requeue): Use serf_reqlist_t members and functions. * src/outgoing.c (reqlist_null): New, static initializer for serf_reqlist_t. (serf_connection_create): Initialize lists with reqlist_null. (request_pending, serf__conn_update_pollset, check_buckets_drained, serf__connection_pre_cleanup, serf_connection__perform_setup, reset_connection, request_writing_finished, read_from_connection, serf_connection_close, serf_connection_queued_requests, serf_connection_pending_requests): Use serf_reqlist_t members and functions. * protocols/http2_protocol.c (http2_outgoing_write): Use serf_reqlist_t members. * protocols/http2_stream.c (serf_http2__stream_setup_next_request, serf_http2__stream_processor): Use serf_reqlist_t members and functions. Modified: serf/branches/SERF-195/protocols/http2_protocol.c serf/branches/SERF-195/protocols/http2_stream.c serf/branches/SERF-195/serf_private.h serf/branches/SERF-195/src/outgoing.c serf/branches/SERF-195/src/outgoing_request.c Modified: serf/branches/SERF-195/protocols/http2_protocol.c ============================================================================== --- serf/branches/SERF-195/protocols/http2_protocol.c Wed Aug 6 10:55:54 2025 (r1927640) +++ serf/branches/SERF-195/protocols/http2_protocol.c Wed Aug 6 12:02:37 2025 (r1927641) @@ -1698,8 +1698,8 @@ http2_outgoing_write(serf_connection_t * serf_http2_protocol_t *h2 = conn->protocol_baton; apr_status_t status; - if (conn->unwritten_reqs - && conn->nr_of_written_reqs < h2->lr_max_concurrent) + if (conn->unwritten_reqs.head + && conn->written_reqs.count < h2->lr_max_concurrent) { status = enqueue_http2_request(h2); if (status) Modified: serf/branches/SERF-195/protocols/http2_stream.c ============================================================================== --- serf/branches/SERF-195/protocols/http2_stream.c Wed Aug 6 10:55:54 2025 (r1927640) +++ serf/branches/SERF-195/protocols/http2_stream.c Wed Aug 6 12:02:37 2025 (r1927641) @@ -339,7 +339,7 @@ serf_http2__stream_setup_next_request(se apr_size_t max_payload_size, serf_hpack_table_t *hpack_tbl) { - serf_request_t *request = conn->unwritten_reqs; + serf_request_t *request = conn->unwritten_reqs.head; apr_status_t status; serf_bucket_t *hpack; serf_bucket_t *body; @@ -359,16 +359,8 @@ serf_http2__stream_setup_next_request(se return status; } - conn->unwritten_reqs = request->next; - if (conn->unwritten_reqs_tail == request) - conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL; - - request->next = NULL; - - serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail, - request); - conn->nr_of_written_reqs++; - conn->nr_of_unwritten_reqs--; + serf__take_request(&conn->unwritten_reqs, request); + serf__push_request(&conn->written_reqs, request); serf__bucket_request_read(request->req_bkt, &body, NULL, NULL); status = serf__bucket_hpack_create_from_request( @@ -802,24 +794,7 @@ serf_http2__stream_processor(void *baton to remove it from the outstanding requests */ { serf_connection_t *conn = serf_request_get_conn(sd->request); - serf_request_t **rq = &conn->written_reqs; - serf_request_t *last = NULL; - - while (*rq && (*rq != sd->request)) { - last = *rq; - rq = &last->next; - } - - if (*rq) - { - (*rq) = sd->request->next; - - if (conn->written_reqs_tail == sd->request) - conn->written_reqs_tail = last; - - conn->nr_of_written_reqs--; - } - + serf__delete_from_reqlist(&conn->written_reqs, sd->request); serf__destroy_request(sd->request); stream->data->request = NULL; } Modified: serf/branches/SERF-195/serf_private.h ============================================================================== --- serf/branches/SERF-195/serf_private.h Wed Aug 6 10:55:54 2025 (r1927640) +++ serf/branches/SERF-195/serf_private.h Wed Aug 6 12:02:37 2025 (r1927641) @@ -262,6 +262,12 @@ typedef enum serf_request_writing_t { SERF_WRITING_FINISHED /* Safe to destroy */ } serf_request_writing_t; +typedef struct serf_reqlist_t { + struct serf_request_t *head; + struct serf_request_t *tail; + unsigned int count; +} serf_reqlist_t; + /* Holds all the information corresponding to a request/response pair. */ struct serf_request_t { serf_connection_t *conn; @@ -307,7 +313,8 @@ struct serf_request_t { for identifying or storing related information */ void *protocol_baton; - struct serf_request_t *next; + serf_request_t *next; + serf_reqlist_t *list; }; struct serf_incoming_request_t @@ -594,20 +601,15 @@ struct serf_connection_t { /* The list of requests that are written but no response has been received yet. */ - serf_request_t *written_reqs; - serf_request_t *written_reqs_tail; - unsigned int nr_of_written_reqs; + serf_reqlist_t written_reqs; /* The list of requests that hasn't been written */ - serf_request_t *unwritten_reqs; - serf_request_t *unwritten_reqs_tail; - unsigned int nr_of_unwritten_reqs; + serf_reqlist_t unwritten_reqs; /* Requests that are done, but not destroyed yet because they may still have data pending in their pools. Will be destroyed at several safe points. */ - serf_request_t *done_reqs; - serf_request_t *done_reqs_tail; + serf_reqlist_t done_reqs; serf_connection_setup_t setup; void *setup_baton; @@ -877,17 +879,17 @@ apr_status_t serf__bucket_hpack_create_f const char *scheme, serf_bucket_alloc_t *allocator); -/* From connection_request.c */ -void serf__link_requests(serf_request_t **list, serf_request_t **tail, - serf_request_t *request); +/* From outgoing_request.c */ +void serf__push_request(serf_reqlist_t *list, serf_request_t *request); +void serf__peek_request(serf_reqlist_t *list, serf_request_t **requestp); +void serf__take_request(serf_reqlist_t *list, serf_request_t *request); +void serf__delete_from_reqlist(serf_reqlist_t *list, serf_request_t *request); apr_status_t serf__destroy_request(serf_request_t *request); apr_status_t serf__cancel_request(serf_request_t *request, - serf_request_t **list, + serf_reqlist_t *list, int notify_request); -unsigned int serf__req_list_length(serf_request_t *req); +void serf__req_list_recalc_length(serf_reqlist_t *req); apr_status_t serf__setup_request(serf_request_t *request); -void serf__link_requests(serf_request_t **list, serf_request_t **tail, - serf_request_t *request); apr_status_t serf__handle_response(serf_request_t *request, apr_pool_t *pool); Modified: serf/branches/SERF-195/src/outgoing.c ============================================================================== --- serf/branches/SERF-195/src/outgoing.c Wed Aug 6 10:55:54 2025 (r1927640) +++ serf/branches/SERF-195/src/outgoing.c Wed Aug 6 12:02:37 2025 (r1927641) @@ -76,7 +76,8 @@ request_pending(serf_request_t **next_re { /* Skip all requests that have been written completely but we're still waiting for a response. */ - serf_request_t *request = conn->unwritten_reqs; + serf_request_t *request; + serf__peek_request(&conn->unwritten_reqs, &request); if (next_req) *next_req = request; @@ -159,8 +160,8 @@ apr_status_t serf__conn_update_pollset(s } } - if ((conn->written_reqs || conn->unwritten_reqs) && - conn->state != SERF_CONN_INIT) { + if ((conn->written_reqs.head || conn->unwritten_reqs.head) + && conn->state != SERF_CONN_INIT) { /* If there are any outstanding events, then we want to read. */ /* ### not true. we only want to read IF we have sent some data */ desc.reqevents |= APR_POLLIN; @@ -204,7 +205,7 @@ apr_status_t serf__conn_update_pollset(s /* Make sure all response buckets were drained. */ static void check_buckets_drained(serf_connection_t *conn) { - serf_request_t *request = conn->written_reqs; + serf_request_t *request = conn->written_reqs.head; for ( ; request ; request = request->next ) { if (request->resp_bkt != NULL) { @@ -220,6 +221,12 @@ static void check_buckets_drained(serf_c #endif +static serf_reqlist_t reqlist_null = { + NULL, /* .head */ + NULL, /* .tail */ + 0 /* .count */ +}; + /* Destroys all outstanding write information, to allow cleanup of subpools that may still have data in these buckets to continue */ void serf__connection_pre_cleanup(serf_connection_t *conn) @@ -230,7 +237,7 @@ void serf__connection_pre_cleanup(serf_c serf_pump__done(&conn->pump); /* Tell all written request that they are free to destroy themselves */ - rq = conn->written_reqs; + rq = conn->written_reqs.head; while (rq != NULL) { if (rq->writing == SERF_WRITING_STARTED || rq->writing == SERF_WRITING_DONE) { @@ -241,13 +248,13 @@ void serf__connection_pre_cleanup(serf_c } /* Destroy the requests that were queued up to destroy later */ - while ((rq = conn->done_reqs)) { - conn->done_reqs = rq->next; + while ((rq = conn->done_reqs.head)) { + serf__take_request(&conn->done_reqs, rq); rq->writing = SERF_WRITING_FINISHED; serf__destroy_request(rq); } - conn->done_reqs = conn->done_reqs_tail = NULL; + conn->done_reqs = reqlist_null; } apr_status_t serf_connection__perform_setup(serf_connection_t *conn) @@ -359,7 +366,7 @@ apr_status_t serf__open_connections(serf } /* Delay opening until we have something to deliver! */ - if (conn->unwritten_reqs == NULL) { + if (conn->unwritten_reqs.head == NULL) { continue; } @@ -475,7 +482,7 @@ static apr_status_t reset_connection(ser { serf_context_t *ctx = conn->ctx; apr_status_t status; - serf_request_t *old_reqs; + serf_reqlist_t old_reqs; serf__log(LOGLVL_DEBUG, LOGCOMP_CONN, __FILE__, conn->config, "reset connection 0x%p\n", conn); @@ -487,8 +494,7 @@ static apr_status_t reset_connection(ser /* Clear the unwritten_reqs queue, so the application can requeue cancelled requests on it for the new socket. */ old_reqs = conn->unwritten_reqs; - conn->unwritten_reqs = NULL; - conn->unwritten_reqs_tail = NULL; + conn->unwritten_reqs = reqlist_null; serf__connection_pre_cleanup(conn); @@ -498,34 +504,34 @@ static apr_status_t reset_connection(ser /* First, cancel all written requests for which we haven't received a response yet. Inform the application that the request is cancelled, so it can requeue them if needed. */ - while (conn->written_reqs) { - serf__cancel_request(conn->written_reqs, &conn->written_reqs, + while (conn->written_reqs.head) { + serf__cancel_request(conn->written_reqs.head, &conn->written_reqs, requeue_requests); } - conn->written_reqs_tail = NULL; + conn->written_reqs = reqlist_null; /* Handle all outstanding unwritten requests. TODO: what about a partially written request? */ - while (old_reqs) { + while (old_reqs.head) { /* If we haven't started to write the connection, bring it over * unchanged to our new socket. * Do not copy a CONNECT request to the new connection, the ssl tunnel * setup code will create a new CONNECT request already. */ - if (requeue_requests && (old_reqs->writing == SERF_WRITING_NONE) && - !old_reqs->ssltunnel) { + old_reqs.head->list = &old_reqs; + if (requeue_requests && (old_reqs.head->writing == SERF_WRITING_NONE) && + !old_reqs.head->ssltunnel) + { - serf_request_t *req = old_reqs; - old_reqs = old_reqs->next; - req->next = NULL; - serf__link_requests(&conn->unwritten_reqs, - &conn->unwritten_reqs_tail, - req); + serf_request_t *req = old_reqs.head; + serf__take_request(&old_reqs, req); + serf__push_request(&conn->unwritten_reqs, req); } - else { + else + { /* We don't want to requeue the request or this request was partially written. Inform the application that the request is cancelled. */ - serf__cancel_request(old_reqs, &old_reqs, requeue_requests); + serf__cancel_request(old_reqs.head, &old_reqs, requeue_requests); } } @@ -577,8 +583,8 @@ static apr_status_t reset_connection(ser conn->seen_in_pollset |= APR_POLLHUP; /* Recalculate the current list length */ - conn->nr_of_written_reqs = 0; - conn->nr_of_unwritten_reqs = serf__req_list_length(conn->unwritten_reqs); + conn->written_reqs.count = 0; + serf__req_list_recalc_length(&conn->unwritten_reqs); /* Found the connection. Closed it. All done. */ return APR_SUCCESS; @@ -625,21 +631,17 @@ static apr_status_t request_writing_fini if (request->writing == SERF_WRITING_DONE) { request->writing = SERF_WRITING_FINISHED; - /* Move the request to the written queue */ - serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail, - request); - conn->nr_of_written_reqs++; - conn->unwritten_reqs = conn->unwritten_reqs->next; - conn->nr_of_unwritten_reqs--; - request->next = NULL; + if (conn->unwritten_reqs.head == request) { + /* Move the request to the written queue */ + serf__take_request(&conn->unwritten_reqs, request); + serf__push_request(&conn->written_reqs, request); + } /* If our connection has async responses enabled, we're not - * going to get a reply back, so kill the request. - */ + * going to get a reply back, so kill the request. + */ if (conn->async_responses) { - conn->unwritten_reqs = request->next; - conn->nr_of_unwritten_reqs--; - serf__destroy_request(request); + serf__destroy_request(request); } conn->completed_requests++; @@ -647,22 +649,15 @@ static apr_status_t request_writing_fini /* Destroy (all) requests that are now safe to destroy, Typically non or just the finished one */ { - serf_request_t *last = NULL; - serf_request_t **rq = &conn->done_reqs; - while (*rq) { - request = *rq; - if ((*rq)->writing == SERF_WRITING_FINISHED) { - request = *rq; - *rq = request->next; + serf_request_t *next; + request = conn->done_reqs.head; + while (request) { + next = request->next; + if (request->writing == SERF_WRITING_FINISHED) { serf__destroy_request(request); } - else { - last = *rq; - rq = &last->next; - } + request = next; } - - conn->done_reqs_tail = last; } return APR_EOF; /* Done with event bucket. Status is ignored */ @@ -813,10 +808,10 @@ static apr_status_t read_from_connection /* Whatever is coming in on the socket corresponds to the first request * on our chain. */ - request = conn->written_reqs; + serf__peek_request(&conn->written_reqs, &request); if (!request) { /* Request wasn't completely written yet! */ - request = conn->unwritten_reqs; + serf__peek_request(&conn->unwritten_reqs, &request); } /* We have a different codepath when we can have async responses. */ @@ -943,24 +938,17 @@ static apr_status_t read_from_connection $ received. * Remove it from our queue and loop to read another response. */ - if (request == conn->written_reqs) { - conn->written_reqs = request->next; - conn->nr_of_written_reqs--; + if (request->list == &conn->written_reqs) { + serf__take_request(&conn->written_reqs, request); } else { - conn->unwritten_reqs = request->next; - conn->nr_of_unwritten_reqs--; + serf__take_request(&conn->unwritten_reqs, request); } serf__destroy_request(request); - request = conn->written_reqs; + serf__peek_request(&conn->written_reqs, &request); if (!request) { - /* Received responses for all written requests */ - conn->written_reqs_tail = NULL; - /* Request wasn't completely written yet! */ - request = conn->unwritten_reqs; - if (!request) - conn->unwritten_reqs_tail = NULL; + serf__peek_request(&conn->unwritten_reqs, &request); } conn->completed_responses++; @@ -968,7 +956,7 @@ static apr_status_t read_from_connection /* We have received a response. If there are no more outstanding requests on this connection, we should stop polling for READ events for now. */ - if (!conn->written_reqs && !conn->unwritten_reqs) { + if (!conn->written_reqs.head && !conn->unwritten_reqs.head) { serf_io__set_pollset_dirty(&conn->io); } @@ -1257,13 +1245,9 @@ serf_connection_t *serf_connection_creat conn->perform_prioritize_request = NULL; conn->protocol_baton = NULL; - conn->written_reqs = conn->written_reqs_tail = NULL; - conn->nr_of_written_reqs = 0; - - conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL; - conn->nr_of_unwritten_reqs = 0; - - conn->done_reqs = conn->done_reqs_tail = 0; + conn->written_reqs = reqlist_null; + conn->unwritten_reqs = reqlist_null; + conn->done_reqs = reqlist_null; /* Create a subpool for our connection. */ apr_pool_create(&conn->skt_pool, conn->pool); @@ -1482,11 +1466,11 @@ apr_status_t serf_connection_close( /* The application asked to close the connection, no need to notify it for each cancelled request. */ - while (conn->written_reqs) { - serf__cancel_request(conn->written_reqs, &conn->written_reqs, 0); + while (conn->written_reqs.head) { + serf__cancel_request(conn->written_reqs.head, &conn->written_reqs, 0); } - while (conn->unwritten_reqs) { - serf__cancel_request(conn->unwritten_reqs, &conn->unwritten_reqs, 0); + while (conn->unwritten_reqs.head) { + serf__cancel_request(conn->unwritten_reqs.head, &conn->unwritten_reqs, 0); } if (conn->skt != NULL) { remove_connection(ctx, conn); @@ -1624,10 +1608,10 @@ apr_interval_time_t serf_connection_get_ unsigned int serf_connection_queued_requests(serf_connection_t *conn) { - return conn->nr_of_unwritten_reqs; + return conn->unwritten_reqs.count; } unsigned int serf_connection_pending_requests(serf_connection_t *conn) { - return conn->nr_of_unwritten_reqs + conn->nr_of_written_reqs; + return conn->unwritten_reqs.count + conn->written_reqs.count; } Modified: serf/branches/SERF-195/src/outgoing_request.c ============================================================================== --- serf/branches/SERF-195/src/outgoing_request.c Wed Aug 6 10:55:54 2025 (r1927640) +++ serf/branches/SERF-195/src/outgoing_request.c Wed Aug 6 12:02:37 2025 (r1927641) @@ -18,6 +18,13 @@ * ==================================================================== */ +#if defined(_DEBUG) +#include <assert.h> +#define SERF__REQLIST_assert(x) assert(x) +#else +#define SERF__REQLIST_assert(x) ((void)0) +#endif + #include <stdlib.h> #include <apr_pools.h> @@ -91,17 +98,36 @@ static apr_status_t clean_resp(void *dat return APR_SUCCESS; } -void serf__link_requests(serf_request_t **list, serf_request_t **tail, - serf_request_t *request) +void serf__push_request(serf_reqlist_t *list, serf_request_t *request) { - if (*list == NULL) { - *list = request; - *tail = request; - } - else { - (*tail)->next = request; - *tail = request; + SERF__REQLIST_assert(request->list == NULL); + request->list = list; + if (list->head == NULL) { + list->head = request; + list->tail = request; + } else { + list->tail->next = request; + list->tail = request; } + ++list->count; +} + +void serf__peek_request(serf_reqlist_t *list, serf_request_t **requestp) +{ + serf_request_t *request = list->head; + SERF__REQLIST_assert(request == NULL || request->list == list); + *requestp = request; +} + +void serf__take_request(serf_reqlist_t *list, serf_request_t *request) +{ + SERF__REQLIST_assert(list->head == request && request->list == list); + list->head = request->next; + if (list->head == NULL) + list->tail = NULL; + --list->count; + request->next = NULL; + request->list = NULL; } apr_status_t serf__destroy_request(serf_request_t *request) @@ -177,6 +203,10 @@ apr_status_t serf__destroy_request(serf_ request->depends_on = NULL; } + if (request->list != NULL) { + serf__delete_from_reqlist(request->list, request); + } + if (request->writing >= SERF_WRITING_STARTED && request->writing < SERF_WRITING_FINISHED) { @@ -185,8 +215,7 @@ apr_status_t serf__destroy_request(serf_ Destroying now will destroy memory of buckets that we may still need. */ - serf__link_requests(&conn->done_reqs, &conn->done_reqs_tail, - request); + serf__push_request(&conn->done_reqs, request); } else { @@ -203,8 +232,33 @@ apr_status_t serf__destroy_request(serf_ return APR_SUCCESS; } +void serf__delete_from_reqlist(serf_reqlist_t *list, serf_request_t *request) +{ + SERF__REQLIST_assert(request->list == list); + + if (list->head == request) { + list->head = request->next; + } else { + serf_request_t *scan = list->head; + + while (scan->next && scan->next != request) + scan = scan->next; + + SERF__REQLIST_assert(scan->next == request); + + scan->next = request->next; + } + + if (list->head == NULL) + list->tail = NULL; + + --list->count; + request->next = NULL; + request->list = NULL; +} + apr_status_t serf__cancel_request(serf_request_t *request, - serf_request_t **list, + serf_reqlist_t *list, int notify_request) { /* If we haven't run setup, then we won't have a handler to call. */ @@ -223,34 +277,23 @@ apr_status_t serf__cancel_request(serf_r SERF_ERROR_HTTP2_CANCEL); } - if (*list == request) { - *list = request->next; - } - else { - serf_request_t *scan = *list; - - while (scan->next && scan->next != request) - scan = scan->next; - - if (scan->next) { - scan->next = scan->next->next; - } - } + serf__delete_from_reqlist(list, request); return serf__destroy_request(request); } /* Calculate the length of a linked list of requests. */ -unsigned int serf__req_list_length(serf_request_t *req) +void serf__req_list_recalc_length(serf_reqlist_t *list) { unsigned int length = 0; + serf_request_t *req = list->head; while (req) { length++; req = req->next; } - return length; + list->count = length; } apr_status_t serf__setup_request(serf_request_t *request) @@ -392,7 +435,7 @@ serf__provide_credentials(serf_context_t /* request->next will be NULL if this was the last request written */ authn_req = request->next; if (!authn_req) - authn_req = conn->unwritten_reqs; + authn_req = conn->unwritten_reqs.head; /* assert: app_request != NULL */ if (!authn_req) @@ -446,6 +489,7 @@ create_request(serf_connection_t *conn, request->depends_next = NULL; request->depends_first = NULL; request->dep_priority = SERF_REQUEST_PRIORITY_DEFAULT; + request->list = NULL; return request; } @@ -462,8 +506,7 @@ serf_request_t *serf_connection_request_ false /* ssl tunnel */); /* Link the request to the end of the request chain. */ - serf__link_requests(&conn->unwritten_reqs, &conn->unwritten_reqs_tail, request); - conn->nr_of_unwritten_reqs++; + serf__push_request(&conn->unwritten_reqs, request); /* Ensure our pollset becomes writable in context run */ serf_io__set_pollset_dirty(&conn->io); @@ -477,8 +520,10 @@ insert_priority_request(serf_request_t * serf_request_t *iter, *prev; serf_connection_t *conn = request->conn; + SERF__REQLIST_assert(request->list == NULL); + /* Link the new request after the last written request. */ - iter = conn->unwritten_reqs; + iter = conn->unwritten_reqs.head; prev = NULL; /* TODO: what if a request is partially written? */ @@ -502,14 +547,19 @@ insert_priority_request(serf_request_t * } } + request->list = &conn->unwritten_reqs; if (prev) { request->next = iter; prev->next = request; + if (conn->unwritten_reqs.tail == prev) + conn->unwritten_reqs.tail = request; } else { request->next = iter; - conn->unwritten_reqs = request; + conn->unwritten_reqs.head = request; + if (conn->unwritten_reqs.tail == NULL) + conn->unwritten_reqs.tail = request; } - conn->nr_of_unwritten_reqs++; + ++conn->unwritten_reqs.count; /* Ensure our pollset becomes writable in context run */ serf_io__set_pollset_dirty(&conn->io); @@ -644,14 +694,16 @@ apr_status_t serf_connection__request_re } /* And now make the discard request take the place of the old request */ - for (pr = &request->conn->written_reqs; *pr; pr = &(*pr)->next) { + discard->list = &request->conn->written_reqs; + for (pr = &request->conn->written_reqs.head; *pr; pr = &(*pr)->next) { if (*pr == request) { *pr = discard; discard->next = request->next; request->next = NULL; + request->list = NULL; if (!discard->next) - request->conn->written_reqs_tail = discard; + request->conn->written_reqs.tail = discard; break; } } @@ -689,18 +741,7 @@ apr_status_t serf_connection__request_re apr_status_t serf_request_cancel(serf_request_t *request) { - serf_connection_t *conn = request->conn; - serf_request_t *tmp = conn->unwritten_reqs; - - /* Find out which queue holds the request */ - while (tmp != NULL && tmp != request) - tmp = tmp->next; - - if (tmp) - return serf__cancel_request(request, &conn->unwritten_reqs, 0); - else - return serf__cancel_request(request, &conn->written_reqs, 0); - + return serf__cancel_request(request, request->list, 0); } void serf_connection_request_prioritize(serf_request_t *request,