{
int i;
log_assert(daemon && daemon->cfg);
- /* only one thread for now */
daemon->num = daemon->cfg->num_threads;
-#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
- if(daemon->num != 1) {
- log_err("configed %d threads, but executable was compiled "
- "with no thread support. Continuing with 1.", daemon->num);
- daemon->num = 1;
- }
-#endif /* no threads */
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
sizeof(struct worker*));
for(i=0; i<daemon->num; i++) {
}
}
+/**
+ * Close all pipes except for the numbered thread.
+ * @param daemon: daemon to close pipes in.
+ * @param thr: thread number 0..num-1 of thread to skip.
+ */
+void close_other_pipes(struct daemon* daemon, int thr)
+{
+ int i;
+ for(i=0; i<daemon->num; i++)
+ if(i!=thr) {
+ if(daemon->workers[i]->cmd_send_fd != -1) {
+ close(daemon->workers[i]->cmd_send_fd);
+ daemon->workers[i]->cmd_send_fd = -1;
+ }
+ if(daemon->workers[i]->cmd_recv_fd != -1) {
+ close(daemon->workers[i]->cmd_recv_fd);
+ daemon->workers[i]->cmd_recv_fd = -1;
+ }
+ }
+}
+
/**
* Function to start one thread.
* @param arg: user argument.
struct worker* worker = (struct worker*)arg;
int num = worker->thread_num;
ub_thread_blocksigs();
+#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
+ /* close pipe ends used by main */
+ close(worker->cmd_send_fd);
+ worker->cmd_send_fd = -1;
+ close_other_pipes(worker->daemon, worker->thread_num);
+#endif /* no threads */
if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports,
BUFSZ, 0))
fatal_exit("Could not initialize thread #%d", num);
for(i=1; i<daemon->num; i++) {
ub_thread_create(&daemon->workers[i]->thr_id,
thread_start, daemon->workers[i]);
+#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
+ /* close pipe end of child */
+ close(daemon->workers[i]->cmd_recv_fd);
+ daemon->workers[i]->cmd_recv_fd = -1;
+#endif /* no threads */
}
}
static void
daemon_stop_others(struct daemon* daemon)
{
- int i, err;
+ int i;
log_assert(daemon);
log_info("stop others");
/* skip i=0, is this thread */
for(i=1; i<daemon->num; i++) {
/* join it to make sure its dead */
log_info("join %d", i);
- if((err=pthread_join(daemon->workers[i]->thr_id, NULL)))
- log_err("pthread_join: %s", strerror(err));
+ ub_thread_join(daemon->workers[i]->thr_id);
log_info("join success %d", i);
}
}
+27 February 2007: Wouter
+ - ub_thread_join portable definition.
+ - forking is used if no threading is available.
+
26 February 2007: Wouter
- ub_random code used to select ID and port.
- log code prints thread id.
#include "config.h"
#include "util/locks.h"
#include <signal.h>
+#include <sys/wait.h>
/** block all signals, masks them away. */
void
ub_thread_blocksigs()
{
-#ifdef HAVE_PTHREAD
int err;
sigset_t sigset;
sigfillset(&sigset);
log_info("blocking signals");
+#ifdef HAVE_PTHREAD
if((err=pthread_sigmask(SIG_SETMASK, &sigset, NULL)))
fatal_exit("pthread_sigmask: %s", strerror(err));
#else
# ifdef HAVE_SOLARIS_THREADS
- int err;
- sigset_t sigset;
- sigfillset(&sigset);
if((err=thr_sigsetmask(SIG_SETMASK, &sigset, NULL)))
fatal_exit("thr_sigsetmask: %s", strerror(err));
# else
- /* have nothing, do nothing */
+ /* have nothing, do single process signal mask */
+ if((err=sigprocmask(SIG_SETMASK, &sigset, NULL)))
+ fatal_exit("sigprocmask: %s", strerror(errno));
# endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */
}
/** unblock one signal, so we can catch it. */
void ub_thread_sig_unblock(int sig)
{
-#ifdef HAVE_PTHREAD
int err;
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, sig);
log_info("unblocking signal %d", sig);
+#ifdef HAVE_PTHREAD
if((err=pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)))
fatal_exit("pthread_sigmask: %s", strerror(err));
#else
# ifdef HAVE_SOLARIS_THREADS
- int err;
- sigset_t sigset;
- sigemptyset(&sigset);
- sigaddset(&sigset, sig);
if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL)))
fatal_exit("thr_sigsetmask: %s", strerror(err));
# else
/* have nothing, do nothing */
+ if((err=sigprocmask(SIG_UNBLOCK, &sigset, NULL)))
+ fatal_exit("sigprocmask: %s", strerror(errno));
# endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */
}
+/**
+ * No threading available: fork a new process.
+ * This means no shared data structure, and no locking.
+ * Only the main thread ever returns. Exits on errors.
+ * @param thr: the location where to store the thread-id.
+ * @param func: function body of the thread. Return value of func is lost.
+ * @param arg: user argument to func.
+ */
+void
+ub_thr_fork_create(ub_thread_t* thr, void* (*func)(void*), void* arg)
+{
+ pid_t pid = fork();
+ switch(pid) {
+ default: /* main */
+ *thr = pid;
+ return;
+ case 0: /* child */
+ *thr = getpid();
+ (void)(*func)(arg);
+ exit(0);
+ case -1: /* error */
+ fatal_exit("could not fork: %s", strerror(errno));
+ }
+}
+
+/**
+ * There is no threading. Wait for a process to terminate.
+ * Note that ub_thread_t is defined as pid_t.
+ * @param thread: the process id to wait for.
+ */
+void ub_thr_fork_wait(ub_thread_t thread)
+{
+ int status = 0;
+ if(waitpid(thread, &status, 0) == -1)
+ log_err("waitpid(%d): %s", (int)thread, strerror(errno));
+ if(status != 0)
+ log_warn("process %d abnormal exit with status %d",
+ (int)thread, status);
+}
#define ub_thread_create(thr, func, arg) LOCKRET(pthread_create(thr, NULL, func, arg))
/** get self id. */
#define ub_thread_self() pthread_self()
+/** wait for another thread to terminate */
+#define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL))
#else /* we do not HAVE_PTHREAD */
#ifdef HAVE_SOLARIS_THREADS
typedef thread_t ub_thread_t;
#define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr))
#define ub_thread_self() thr_self()
+#define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL))
#else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */
#define lock_quick_unlock(lock) /* nop */
/** Thread creation, threads do not exist */
-typedef int ub_thread_t;
+typedef pid_t ub_thread_t;
/** ub_thread_create gives an error, it should not be called. */
#define ub_thread_create(thr, func, arg) \
+ ub_thr_fork_create(thr, func, arg)
fatal_exit("%s %d called thread create, but no thread support " \
"has been compiled in.", __FILE__, __LINE__)
-#define ub_thread_self() 0
+#define ub_thread_self() getpid()
+#define ub_thread_join(thread) ub_thr_fork_wait(thread)
#endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */