From 281c4d49638e52a37d2026b8bdfece3f4a9b5eec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 27 Jul 2008 23:13:18 +0200 Subject: add code to detect if a worker thread/process died --- libasyncns/asyncns.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) (limited to 'libasyncns') diff --git a/libasyncns/asyncns.c b/libasyncns/asyncns.c index 2801e2e..3c94f3b 100644 --- a/libasyncns/asyncns.c +++ b/libasyncns/asyncns.c @@ -22,7 +22,7 @@ #include #endif -/*#undef HAVE_PTHREAD */ +/* #undef HAVE_PTHREAD */ #include #include @@ -63,7 +63,8 @@ typedef enum { REQUEST_RES_QUERY, REQUEST_RES_SEARCH, RESPONSE_RES, - REQUEST_TERMINATE + REQUEST_TERMINATE, + RESPONSE_DIED } query_type_t; enum { @@ -90,6 +91,7 @@ struct asyncns { asyncns_query_t *done_head, *done_tail; int n_queries; + int dead; }; struct asyncns_query { @@ -358,6 +360,18 @@ static int fd_cloexec(int fd) { return fcntl(fd, F_SETFD, v | FD_CLOEXEC); } +static int send_died(int out_fd) { + rheader_t rh; + assert(out_fd > 0); + + memset(&rh, 0, sizeof(rh)); + rh.type = RESPONSE_DIED; + rh.id = 0; + rh.length = sizeof(rh); + + return send(out_fd, &rh, rh.length, 0); +} + static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) { addrinfo_serialization_t s; size_t cnl, l; @@ -651,8 +665,7 @@ static int process_worker(int in_fd, int out_fd) { fail: - close(in_fd); - close(out_fd); + send_died(out_fd); return 0; } @@ -690,6 +703,8 @@ static void* thread_worker(void *p) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); } + send_died(out_fd); + return NULL; } @@ -707,6 +722,7 @@ asyncns_t* asyncns_new(unsigned n_proc) { if (!(asyncns = malloc(sizeof(asyncns_t)))) goto fail; + asyncns->dead = 0; asyncns->valid_workers = 0; for (i = 0; i < 4; i++) @@ -895,6 +911,11 @@ static int handle_response(asyncns_t *asyncns, rheader_t *resp, size_t length) { assert(length >= sizeof(rheader_t)); assert(length == resp->length); + if (resp->type == RESPONSE_DIED) { + asyncns->dead = 1; + return 0; + } + if (!(q = lookup_query(asyncns, resp->id))) return 0; @@ -982,6 +1003,11 @@ int asyncns_wait(asyncns_t *asyncns, int block) { rheader_t buf[BUFSIZE/sizeof(rheader_t) + 1]; ssize_t l; + if (asyncns->dead) { + errno = ECHILD; + return -1; + } + if (((l = recv(asyncns->fds[RESPONSE_RECV_FD], buf, sizeof(buf), 0)) < 0)) { fd_set fds; @@ -1047,6 +1073,11 @@ asyncns_query_t* asyncns_getaddrinfo(asyncns_t *asyncns, const char *node, const assert(asyncns); assert(node || service); + if (asyncns->dead) { + errno = ECHILD; + return NULL; + } + if (!(q = alloc_query(asyncns))) return NULL; @@ -1094,6 +1125,11 @@ int asyncns_getaddrinfo_done(asyncns_t *asyncns, asyncns_query_t* q, struct addr assert(q->asyncns == asyncns); assert(q->type == REQUEST_ADDRINFO); + if (asyncns->dead) { + errno = ECHILD; + return EAI_SYSTEM; + } + if (!q->done) return EAI_AGAIN; @@ -1114,6 +1150,11 @@ asyncns_query_t* asyncns_getnameinfo(asyncns_t *asyncns, const struct sockaddr * assert(sa); assert(salen > 0); + if (asyncns->dead) { + errno = ECHILD; + return NULL; + } + if (!(q = alloc_query(asyncns))) return NULL; @@ -1154,6 +1195,11 @@ int asyncns_getnameinfo_done(asyncns_t *asyncns, asyncns_query_t* q, char *ret_h assert(!ret_host || hostlen); assert(!ret_serv || servlen); + if (asyncns->dead) { + errno = ECHILD; + return EAI_SYSTEM; + } + if (!q->done) return EAI_AGAIN; @@ -1181,6 +1227,11 @@ static asyncns_query_t * asyncns_res(asyncns_t *asyncns, query_type_t qtype, con assert(asyncns); assert(dname); + if (asyncns->dead) { + errno = ECHILD; + return NULL; + } + if (!(q = alloc_query(asyncns))) return NULL; @@ -1228,7 +1279,13 @@ int asyncns_res_done(asyncns_t *asyncns, asyncns_query_t* q, unsigned char **ans assert(q->type == REQUEST_RES_QUERY || q->type == REQUEST_RES_SEARCH); assert(answer); - if (!q->done) + if (asyncns->dead) { + errno = ECHILD; + return -ECHILD; + } + + if (!q->done) { + errno = EAGAIN; return -EAGAIN; *answer = (unsigned char *)q->serv; -- cgit