mirror of https://github.com/getdnsapi/getdns.git
atomic netreq removal from write_queue in upstream_write_cb
This commit is contained in:
parent
6afcc97b87
commit
968d94d2be
54
src/stub.c
54
src/stub.c
|
@ -462,6 +462,36 @@ stub_next_upstream(getdns_network_req *netreq)
|
||||||
dnsreq->upstreams->current_udp = 0;
|
dnsreq->upstreams->current_udp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_from_write_queue(getdns_upstream *upstream, getdns_network_req * netreq)
|
||||||
|
{
|
||||||
|
getdns_network_req *r, *prev_r;
|
||||||
|
|
||||||
|
for ( r = upstream->write_queue, prev_r = NULL
|
||||||
|
; r
|
||||||
|
; prev_r = r, r = r->write_queue_tail) {
|
||||||
|
|
||||||
|
if (r != netreq)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (prev_r)
|
||||||
|
prev_r->write_queue_tail = r->write_queue_tail;
|
||||||
|
else
|
||||||
|
upstream->write_queue = r->write_queue_tail;
|
||||||
|
|
||||||
|
if (r == upstream->write_queue_last) {
|
||||||
|
/* If r was the last netreq,
|
||||||
|
* its write_queue tail MUST be NULL
|
||||||
|
*/
|
||||||
|
assert(r->write_queue_tail == NULL);
|
||||||
|
upstream->write_queue_last = prev_r ? prev_r : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
netreq->write_queue_tail = NULL;
|
||||||
|
break; /* netreq found and removed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stub_cleanup(getdns_network_req *netreq)
|
stub_cleanup(getdns_network_req *netreq)
|
||||||
{
|
{
|
||||||
|
@ -481,22 +511,7 @@ stub_cleanup(getdns_network_req *netreq)
|
||||||
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
||||||
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
||||||
|
|
||||||
/* Delete from upstream->write_queue (if present) */
|
remove_from_write_queue(upstream, netreq);
|
||||||
for (prev_r = NULL, r = upstream->write_queue; r;
|
|
||||||
prev_r = r, r = r->write_queue_tail)
|
|
||||||
|
|
||||||
if (r == netreq) {
|
|
||||||
if (prev_r)
|
|
||||||
prev_r->write_queue_tail = r->write_queue_tail;
|
|
||||||
else
|
|
||||||
upstream->write_queue = r->write_queue_tail;
|
|
||||||
|
|
||||||
if (r == upstream->write_queue_last)
|
|
||||||
upstream->write_queue_last =
|
|
||||||
prev_r ? prev_r : NULL;
|
|
||||||
netreq->write_queue_tail = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
|
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1706,8 +1721,11 @@ upstream_write_cb(void *userarg)
|
||||||
upstream->queries_sent++;
|
upstream->queries_sent++;
|
||||||
|
|
||||||
/* Unqueue the netreq from the write_queue */
|
/* Unqueue the netreq from the write_queue */
|
||||||
if (!(upstream->write_queue = netreq->write_queue_tail)) {
|
remove_from_write_queue(upstream, netreq);
|
||||||
upstream->write_queue_last = NULL;
|
|
||||||
|
/* Empty write_queue?, then deschedule upstream write_cb */
|
||||||
|
if (upstream->write_queue == NULL) {
|
||||||
|
assert(upstream->write_queue_last == NULL);
|
||||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||||
upstream->event.write_cb = NULL;
|
upstream->event.write_cb = NULL;
|
||||||
/* Reschedule (if already reading) to clear writable */
|
/* Reschedule (if already reading) to clear writable */
|
||||||
|
|
Loading…
Reference in New Issue