X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fevent.c;h=10d64b1da0c356575b7e5a50452e02f845ec1030;hb=fc440c64836370db9d8cb1a25f09c9df0786f865;hp=39b67b75ad6d025538d233f245e98ae1812c4660;hpb=777763cb0994893c42f4030a442d3d44a403b8fa;p=adns.git diff --git a/src/event.c b/src/event.c index 39b67b7..10d64b1 100644 --- a/src/event.c +++ b/src/event.c @@ -6,7 +6,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -209,11 +209,16 @@ static void timeouts_queue(adns_state ads, int act, struct timeval **tv_io, struct timeval *tvbuf, struct timeval now, struct query_queue *queue) { adns_query qu, nqu; + struct timeval expires; for (qu= queue->head; qu; qu= nqu) { nqu= qu->next; - if (!timercmp(&now,&qu->timeout,>)) { - inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); + if (timercmp(&now,&qu->timeout_started,<)) /* clock rewound */ + qu->timeout_started= now; + expires= qu->timeout_started; + timevaladd(&expires, qu->timeout_ms); + if (!timercmp(&now,&expires,>)) { + inter_maxtoabs(tv_io,tvbuf,now,expires); } else { if (!act) { inter_immed(tv_io,tvbuf); return; } LIST_UNLINK(*queue,qu); @@ -284,7 +289,7 @@ void adns__timeouts(adns_state ads, int act, void adns_firsttimeout(adns_state ads, struct timeval **tv_io, struct timeval *tvbuf, struct timeval now) { - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__timeouts(ads, 0, tv_io,tvbuf, now); adns__returning(ads,0); } @@ -292,7 +297,7 @@ void adns_firsttimeout(adns_state ads, void adns_processtimeouts(adns_state ads, const struct timeval *now) { struct timeval tv_buf; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__must_gettimeofday(ads,&now,&tv_buf); if (now) adns__timeouts(ads, 1, 0,0, *now); adns__returning(ads,0); @@ -346,7 +351,7 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { struct udpsocket *udp; adns_sockaddr udpaddr; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: @@ -433,7 +438,7 @@ xit: int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { int r; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: @@ -461,7 +466,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { } assert(FD_ISSET(ads->tcpsocket,&writeable)); if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; } - r= read(ads->tcpsocket,&ads->tcprecv.buf,1); + r= read(ads->tcpsocket,ads->tcprecv.buf,1); if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) { tcp_connected(ads,*now); r= 0; goto xit; @@ -488,6 +493,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { adns__tcp_broken(ads,"write",strerror(errno)); r= 0; goto xit; } else if (r>0) { + assert(r <= ads->tcpsend.used); ads->tcpsend.used -= r; memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used); } @@ -505,7 +511,7 @@ xit: int adns_processexceptional(adns_state ads, int fd, const struct timeval *now) { - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: case server_broken: @@ -574,7 +580,7 @@ void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io, struct pollfd pollfds[MAX_POLLFDS]; int i, fd, maxfd, npollfds; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); if (tv_mod && (!*tv_mod || (*tv_mod)->tv_sec || (*tv_mod)->tv_usec)) { /* The caller is planning to sleep. */ @@ -605,7 +611,7 @@ void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds, struct pollfd pollfds[MAX_POLLFDS]; int npollfds, i; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__must_gettimeofday(ads,&now,&tv_buf); if (!now) goto xit; adns_processtimeouts(ads,now); @@ -623,10 +629,24 @@ xit: /* General helpful functions. */ void adns_globalsystemfailure(adns_state ads) { - adns__consistency(ads,0,cc_entex); + /* Must not be called by adns during actual processing of a + * particular query, since it reenters adns. Only safe to call in + * situations where it would be safe to call adns_returning. */ + adns__consistency(ads,0,cc_enter); - while (ads->udpw.head) adns__query_fail(ads->udpw.head, adns_s_systemfail); - while (ads->tcpw.head) adns__query_fail(ads->tcpw.head, adns_s_systemfail); + for (;;) { + adns_query qu; +#define GSF_QQ(QQ) \ + if ((qu= ads->QQ.head)) { \ + LIST_UNLINK(ads->QQ,qu); \ + adns__query_fail(qu, adns_s_systemfail); \ + continue; \ + } + GSF_QQ(udpw); + GSF_QQ(tcpw); +#undef GSF_QQ + break; + } switch (ads->tcpstate) { case server_connecting: @@ -648,7 +668,7 @@ int adns_processany(adns_state ads) { struct pollfd pollfds[MAX_POLLFDS]; int npollfds; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); r= gettimeofday(&now,0); if (!r) adns_processtimeouts(ads,&now); @@ -707,7 +727,7 @@ int adns_wait(adns_state ads, fd_set readfds, writefds, exceptfds; struct timeval tvbuf, *tvp; - adns__consistency(ads,*query_io,cc_entex); + adns__consistency(ads,*query_io,cc_enter); for (;;) { r= adns__internal_check(ads,query_io,answer_r,context_r); if (r != EAGAIN) break; @@ -739,7 +759,7 @@ int adns_check(adns_state ads, struct timeval now; int r; - adns__consistency(ads,*query_io,cc_entex); + adns__consistency(ads,*query_io,cc_enter); r= gettimeofday(&now,0); if (!r) adns__autosys(ads,now);