From 03fbffbda4d36188944a4df39eace449a0c306dd Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 15 Oct 2009 10:39:10 -0700 Subject: [PATCH] Make sure that time advances in a daemon between calls to time_refresh(). Open vSwitch uses an interval timer signal to tell it that its cached idea of the current time has expired. However, this didn't work in a daemon detached from the foreground session (invoked with --detach) because a child created with fork() does not inherit the parent's interval timer and we did not re-set it after calling fork(). This commit fixes the problem by setting the interval timer back up after calling fork() from daemonize(). This fix is based on code inspection (which was then verified to be correct through testing). It may not fix any actual problems in practice, because time_refresh() is called every time through the poll loop, and the poll loop typically runs more quickly than the periodic timer fires (1 ms or so average in ovs-vswitchd, vs. 100 ms timer interval). --- lib/daemon.c | 2 ++ lib/timeval.c | 24 +++++++++++++++++++++--- lib/timeval.h | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/daemon.c b/lib/daemon.c index 1e3f0029..a35c6393 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -23,6 +23,7 @@ #include #include "fatal-signal.h" #include "dirs.h" +#include "timeval.h" #include "util.h" #define THIS_MODULE VLM_daemon @@ -222,6 +223,7 @@ daemonize(void) if (chdir_) { chdir("/"); } + time_postfork(); break; case -1: diff --git a/lib/timeval.c b/lib/timeval.c index 3cca338f..314b3f43 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -43,6 +43,7 @@ static struct timeval now; /* Time at which to die with SIGALRM (if not TIME_MIN). */ static time_t deadline = TIME_MIN; +static void setup_timer(void); static void sigalrm_handler(int); static void refresh_if_ticked(void); static time_t time_add(time_t, time_t); @@ -57,8 +58,6 @@ void time_init(void) { struct sigaction sa; - struct itimerval itimer; - if (inited) { return; } @@ -78,7 +77,15 @@ time_init(void) ovs_fatal(errno, "sigaction(SIGALRM) failed"); } - /* Set up periodic timer. */ + /* Set up periodic signal. */ + setup_timer(); +} + +static void +setup_timer(void) +{ + struct itimerval itimer; + itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = TIME_UPDATE_INTERVAL * 1000; itimer.it_value = itimer.it_interval; @@ -87,6 +94,17 @@ time_init(void) } } +/* Set up the interval timer, to ensure that time advances even without calling + * time_refresh(). + * + * A child created with fork() does not inherit the parent's interval timer, so + * this function needs to be called from the child after fork(). */ +void +time_postfork(void) +{ + setup_timer(); +} + /* Forces a refresh of the current time from the kernel. It is not usually * necessary to call this function, since the time will be refreshed * automatically at least every TIME_UPDATE_INTERVAL milliseconds. */ diff --git a/lib/timeval.h b/lib/timeval.h index 660a2074..8567d754 100644 --- a/lib/timeval.h +++ b/lib/timeval.h @@ -41,6 +41,7 @@ BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t)); #define TIME_UPDATE_INTERVAL 100 void time_init(void); +void time_postfork(void); void time_refresh(void); time_t time_now(void); long long int time_msec(void); -- 2.30.2