From ac868fa87da18cdebb86103b35ce250bd171f700 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 11 Apr 1999 21:01:49 +0000 Subject: [PATCH] SIGPIPE protection available. --- src/adns.h | 1 + src/event.c | 2 ++ src/general.c | 29 +++++++++++++++++++++++++++++ src/internal.h | 13 ++++++++++++- src/transmit.c | 2 ++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/adns.h b/src/adns.h index 32addba..5726e25 100644 --- a/src/adns.h +++ b/src/adns.h @@ -42,6 +42,7 @@ typedef enum { adns_if_debug= 0x0008, /* enable all output to stderr plus debug msgs */ adns_if_noautosys= 0x0010, /* do not make syscalls at every opportunity */ adns_if_eintr= 0x0020, /* allow _wait and _synchronous to return EINTR */ + adns_if_nosigpipe= 0x0040, /* applic has SIGPIPE set to SIG_IGN, do not protect */ } adns_initflags; typedef enum { diff --git a/src/event.c b/src/event.c index 5041f8c..db3dad6 100644 --- a/src/event.c +++ b/src/event.c @@ -284,7 +284,9 @@ static int internal_callback(adns_state ads, int maxfd, } else if (callb_checkfd(maxfd,exceptfds,ads->tcpsocket)) { adns__tcp_broken(ads,"select","exceptional condition detected"); } else if (ads->tcpsend.used && callb_checkfd(maxfd,writefds,ads->tcpsocket)) { + adns__sigpipe_protect(ads); r= write(ads->tcpsocket,ads->tcpsend.buf,ads->tcpsend.used); + adns__sigpipe_unprotect(ads); if (r<0) { if (errno!=EAGAIN && errno!=EWOULDBLOCK && errno!=ENOMEM && errno!=EINTR) { adns__tcp_broken(ads,"write",strerror(errno)); diff --git a/src/general.c b/src/general.c index 33946ad..b701b9f 100644 --- a/src/general.c +++ b/src/general.c @@ -270,3 +270,32 @@ void adns__isort(void *array, int nobjs, int sz, void *tempbuf, } } } + +/* SIGPIPE protection. */ + +void adns__sigpipe_protect(adns_state ads) { + sigset_t toblock; + struct sigaction sa; + int r; + + if (ads->iflags & adns_if_nosigpipe) return; + + sigfillset(&toblock); + sigdelset(&toblock,SIGPIPE); + + sa.sa_handler= SIG_IGN; + sigfillset(&sa.sa_mask); + sa.sa_flags= 0; + + r= sigprocmask(SIG_SETMASK,&toblock,&ads->stdsigmask); assert(!r); + r= sigaction(SIGPIPE,&sa,&ads->stdsigpipe); assert(!r); +} + +void adns__sigpipe_unprotect(adns_state ads) { + int r; + + if (ads->iflags & adns_if_nosigpipe) return; + + r= sigaction(SIGPIPE,&ads->stdsigpipe,0); assert(!r); + r= sigprocmask(SIG_SETMASK,&ads->stdsigmask,0); assert(!r); +} diff --git a/src/internal.h b/src/internal.h index 5e42ade..9a5f23d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -31,6 +31,7 @@ typedef unsigned char byte; #include #include #include +#include #include @@ -249,6 +250,8 @@ struct adns__state { int nservers, nsortlist, tcpserver; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; + struct sigaction stdsigpipe; + sigset_t stdsigmask; struct server { struct in_addr addr; } servers[MAXSERVERS]; @@ -302,7 +305,15 @@ void adns__isort(void *array, int nobjs, int sz, void *tempbuf, * sz bytes long. needswap should return !0 if a>b (strictly, ie * wrong order) 0 if a<=b (ie, order is fine). */ - + +void adns__sigpipe_protect(adns_state); +void adns__sigpipe_unprotect(adns_state); +/* If SIGPIPE protection is not disabled, will block all signals except + * SIGPIPE, and set SIGPIPE's disposition to SIG_IGN. (And then restore.) + * Each call to _protect must be followed by a call to _unprotect before + * any significant amount of code gets to run. + */ + /* From transmit.c: */ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r, diff --git a/src/transmit.c b/src/transmit.c index d3978c3..d0b9d95 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -179,7 +179,9 @@ void adns__query_tcp(adns_query qu, struct timeval now) { iov[0].iov_len= 2; iov[1].iov_base= qu->query_dgram; iov[1].iov_len= qu->query_dglen; + adns__sigpipe_protect(qu->ads); wr= writev(qu->ads->tcpsocket,iov,2); + adns__sigpipe_unprotect(qu->ads); if (wr < 0) { if (!(errno == EAGAIN || errno == EINTR || errno == ENOSPC || errno == ENOBUFS || errno == ENOMEM)) { -- 2.30.2