diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-06-28 10:53:34 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-06-28 11:18:13 -0400 |
commit | 315e6b59ddb91c19c5102625c6cf0f22b2d6f894 (patch) | |
tree | 6b8b4a72d3ebd1292307de21b9acf8c4c3810d35 /src/common/util_process.c | |
parent | ec4eee63561c3f6a8bb0c466f17b92e99f832c5d (diff) | |
download | tor-315e6b59ddb91c19c5102625c6cf0f22b2d6f894.tar.gz tor-315e6b59ddb91c19c5102625c6cf0f22b2d6f894.zip |
Extract process-management functionality into a new lib/process
Note that procmon does *not* go here, since procmon needs to
integrate with the event loop.
Diffstat (limited to 'src/common/util_process.c')
-rw-r--r-- | src/common/util_process.c | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/src/common/util_process.c b/src/common/util_process.c deleted file mode 100644 index 321258b694..0000000000 --- a/src/common/util_process.c +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright (c) 2003-2004, Roger Dingledine - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2018, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file util_process.c - * \brief utility functions for launching processes and checking their - * status. These functions are kept separately from procmon so that they - * won't require linking against libevent. - **/ - -#include "orconfig.h" - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#include "common/compat.h" -#include "common/util.h" -#include "lib/log/torlog.h" -#include "common/util_process.h" -#include "ht.h" - -/* ================================================== */ -/* Convenience structures for handlers for waitpid(). - * - * The tor_process_monitor*() code above doesn't use them, since it is for - * monitoring a non-child process. - */ - -#ifndef _WIN32 - -/** Mapping from a PID to a userfn/userdata pair. */ -struct waitpid_callback_t { - HT_ENTRY(waitpid_callback_t) node; - pid_t pid; - - void (*userfn)(int, void *userdata); - void *userdata; - - unsigned running; -}; - -static inline unsigned int -process_map_entry_hash_(const waitpid_callback_t *ent) -{ - return (unsigned) ent->pid; -} - -static inline unsigned int -process_map_entries_eq_(const waitpid_callback_t *a, - const waitpid_callback_t *b) -{ - return a->pid == b->pid; -} - -static HT_HEAD(process_map, waitpid_callback_t) process_map = HT_INITIALIZER(); - -HT_PROTOTYPE(process_map, waitpid_callback_t, node, process_map_entry_hash_, - process_map_entries_eq_) -HT_GENERATE2(process_map, waitpid_callback_t, node, process_map_entry_hash_, - process_map_entries_eq_, 0.6, tor_reallocarray_, tor_free_) - -/** - * Begin monitoring the child pid <b>pid</b> to see if we get a SIGCHLD for - * it. If we eventually do, call <b>fn</b>, passing it the exit status (as - * yielded by waitpid) and the pointer <b>arg</b>. - * - * To cancel this, or clean up after it has triggered, call - * clear_waitpid_callback(). - */ -waitpid_callback_t * -set_waitpid_callback(pid_t pid, void (*fn)(int, void *), void *arg) -{ - waitpid_callback_t *old_ent; - waitpid_callback_t *ent = tor_malloc_zero(sizeof(waitpid_callback_t)); - ent->pid = pid; - ent->userfn = fn; - ent->userdata = arg; - ent->running = 1; - - old_ent = HT_REPLACE(process_map, &process_map, ent); - if (old_ent) { - log_warn(LD_BUG, "Replaced a waitpid monitor on pid %u. That should be " - "impossible.", (unsigned) pid); - old_ent->running = 0; - } - - return ent; -} - -/** - * Cancel a waitpid_callback_t, or clean up after one has triggered. Releases - * all storage held by <b>ent</b>. - */ -void -clear_waitpid_callback(waitpid_callback_t *ent) -{ - waitpid_callback_t *old_ent; - if (ent == NULL) - return; - - if (ent->running) { - old_ent = HT_REMOVE(process_map, &process_map, ent); - if (old_ent != ent) { - log_warn(LD_BUG, "Couldn't remove waitpid monitor for pid %u.", - (unsigned) ent->pid); - return; - } - } - - tor_free(ent); -} - -/** Helper: find the callack for <b>pid</b>; if there is one, run it, - * reporting the exit status as <b>status</b>. */ -static void -notify_waitpid_callback_by_pid(pid_t pid, int status) -{ - waitpid_callback_t search, *ent; - - search.pid = pid; - ent = HT_REMOVE(process_map, &process_map, &search); - if (!ent || !ent->running) { - log_info(LD_GENERAL, "Child process %u has exited; no callback was " - "registered", (unsigned)pid); - return; - } - - log_info(LD_GENERAL, "Child process %u has exited; running callback.", - (unsigned)pid); - - ent->running = 0; - ent->userfn(status, ent->userdata); -} - -/** Use waitpid() to wait for all children that have exited, and invoke any - * callbacks registered for them. */ -void -notify_pending_waitpid_callbacks(void) -{ - /* I was going to call this function reap_zombie_children(), but - * that makes it sound way more exciting than it really is. */ - pid_t child; - int status = 0; - - while ((child = waitpid(-1, &status, WNOHANG)) > 0) { - notify_waitpid_callback_by_pid(child, status); - status = 0; /* should be needless */ - } -} - -#endif /* !defined(_WIN32) */ - |