From 8c087f026cbf0665be8625b55a19a968e4e50949 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sun, 11 Nov 2007 13:28:42 -0500 Subject: [PATCH] Thread attributes are copied in pth_spawn() so it's safe to reuse the attr object. Reset a connection thread priority to standard in socket_thread() because threads inherit attributes. Be nicer about terminating the socket_thread. Check for an exception in the event and terminate the thread if theres an pth_accept() error. This will occur when a terminating signal is sent which closes the socket file descriptor. Added xdump() to mem.c which shows not-freed pointers which is enabled when DEBUG is defined. --- src/mem.c | 8 ++++++++ src/mem.h | 1 + src/pwmd.c | 68 +++++++++++++++++++++++++++++++++++++------------------------- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/mem.c b/src/mem.c index f054407f..f7c7d28d 100644 --- a/src/mem.c +++ b/src/mem.c @@ -223,3 +223,11 @@ void xpanic(void) for (m = memlist; m; m = memlist) xfree(m->ptr); } + +void xdump(void) +{ + struct memlist_s *m; + + for (m = memlist; m; m = m->next) + fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size); +} diff --git a/src/mem.h b/src/mem.h index b64f29fe..f5fee610 100644 --- a/src/mem.h +++ b/src/mem.h @@ -36,6 +36,7 @@ void *xrealloc(void *ptr, size_t size) __attribute__ ((visibility ("hidden"))); char *xstrdup(const char *str) __attribute__ ((visibility ("hidden"))); void *xcalloc(size_t nmemb, size_t size) __attribute__ ((visibility ("hidden"))); void xpanic(void) __attribute__ ((visibility ("hidden"))); +void xdump(void) __attribute__ ((visibility ("hidden"))); #ifdef __cplusplus } diff --git a/src/pwmd.c b/src/pwmd.c index ccae0dbe..a8c4c125 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -996,8 +996,17 @@ static void *socket_thread(void *arg) { pth_event_t ev; gint sockfd = (gint)arg; + pth_attr_t attr; - ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE, sockfd); + /* + * Thread priority is inherited from the calling thread. This thread is + * PTH_PRIO_MAX. Keep the "child" threads at standard priority. + */ + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_STD); + + ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|PTH_UNTIL_FD_EXCEPTION, sockfd); for (;;) { socklen_t slen = sizeof(struct sockaddr_un); @@ -1007,8 +1016,10 @@ static void *socket_thread(void *arg) if (pth_wait(ev) && pth_event_occurred(ev)) { if ((fd = pth_accept(sockfd, (struct sockaddr *)&raddr, &slen)) == -1) { - if (!quit && errno != EAGAIN && errno != EINTR) { - log_write("accept(): %s", strerror(errno)); + if (errno != EAGAIN) { + if (!quit) // probably EBADF + log_write("accept(): %s", strerror(errno)); + break; } } @@ -1019,7 +1030,7 @@ static void *socket_thread(void *arg) struct client_thread_s *new; log_write(N_("new connection: fd=%i"), fd); - tid = pth_spawn(NULL, doit, (void *)fd); + tid = pth_spawn(attr, doit, (void *)fd); if (!tid) { log_write(N_("pth_spawn() failed")); @@ -1046,6 +1057,8 @@ static void *socket_thread(void *arg) } pth_event_free(ev, PTH_FREE_THIS); + pth_attr_destroy(attr); + pth_exit(PTH_CANCELED); return NULL; } @@ -1083,7 +1096,7 @@ static void server_loop(int sockfd) guint n, i; sigset_t set; gint n_clients = 0; - pth_attr_t socket_attr, cleanup_attr, timeout_attr; + pth_attr_t attr; pth_event_t timeout_event; gpointer value; @@ -1104,28 +1117,28 @@ static void server_loop(int sockfd) */ pth_fdmode(sockfd, PTH_FDMODE_NONBLOCK); - socket_attr = pth_attr_new(); - pth_attr_init(socket_attr); - pth_attr_set(socket_attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); - pth_attr_set(socket_attr, PTH_ATTR_JOINABLE, FALSE); - pth_attr_set(socket_attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_ASYNCHRONOUS); - socket_tid = pth_spawn(socket_attr, socket_thread, (void *)sockfd); - cleanup_attr = pth_attr_new(); - pth_attr_init(cleanup_attr); - pth_attr_set(cleanup_attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); - pth_attr_set(cleanup_attr, PTH_ATTR_JOINABLE, FALSE); - pth_attr_set(cleanup_attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_ASYNCHRONOUS); - cleanup_tid = pth_spawn(cleanup_attr, cleanup_thread, NULL); + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); + socket_tid = pth_spawn(attr, socket_thread, (void *)sockfd); + pth_attr_destroy(attr); + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MAX); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set(attr, PTH_ATTR_CANCEL_STATE, PTH_CANCEL_ASYNCHRONOUS); + cleanup_tid = pth_spawn(attr, cleanup_thread, NULL); + pth_attr_init(attr); /* * For the cache_timeout configuration parameter. This replaces the old * SIGALRM stuff and is safer. */ timeout_event = pth_event(PTH_EVENT_TIME, pth_timeout(1, 0)); - timeout_attr = pth_attr_new(); - pth_attr_init(timeout_attr); - pth_attr_set(timeout_attr, PTH_ATTR_JOINABLE, FALSE); - pth_attr_set(timeout_attr, PTH_ATTR_PRIO, PTH_PRIO_MIN); + attr = pth_attr_new(); + pth_attr_init(attr); + pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE); + pth_attr_set(attr, PTH_ATTR_PRIO, PTH_PRIO_MIN); do { gint sig = 0; @@ -1138,7 +1151,7 @@ static void server_loop(int sockfd) * cache mutex is locked and the timer expires again, the threads * will stack. */ - pth_spawn(timeout_attr, adjust_cache_time_thread, NULL); + pth_spawn(attr, adjust_cache_time_thread, NULL); pth_event_free(timeout_event, PTH_FREE_THIS); timeout_event = pth_event(PTH_EVENT_TIME, pth_timeout(1, 0)); } @@ -1170,6 +1183,7 @@ static void server_loop(int sockfd) quit = 1; shutdown(sockfd, SHUT_RDWR); close(sockfd); + pth_join(socket_tid, &value); break; } } @@ -1180,8 +1194,7 @@ static void server_loop(int sockfd) * to terminate the daemon. We'll wait for all clients to disconnect * before exiting and ignore any following signals. */ - pth_abort(socket_tid); - pth_attr_destroy(socket_attr); + pth_attr_destroy(attr); pth_event_free(timeout_event, PTH_FREE_THIS); n = pth_ctrl(PTH_CTRL_GETTHREADS); @@ -1217,8 +1230,6 @@ static void server_loop(int sockfd) } pth_cancel(cleanup_tid); - pth_join(cleanup_tid, &value); - pth_attr_destroy(cleanup_attr); } int main(int argc, char *argv[]) @@ -1561,6 +1572,9 @@ do_exit: if (estatus == EXIT_SUCCESS) log_write(N_("pwmd exiting normally")); - pth_exit(0); +#if defined(DEBUG) && !defined(MEM_DEBUG) + xdump(); +#endif + pth_kill(); exit(estatus); } -- 2.11.4.GIT