2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-04 16:25:17 +00:00

cfg: Fix implementation of timeout in attempting to lock the config file.

Without removing SA_RESTART from the SIGALRM handler, the fcntl call will
never return, even after the signal handler is invoked and returns.

We haven't seen a problem in practice, at least not recently, but that's
probably just luck combined with not holding the configuration file lock
for very long.
This commit is contained in:
Ben Pfaff
2009-10-15 10:42:59 -07:00
parent e7cfedd6de
commit dc81071d9f
3 changed files with 47 additions and 6 deletions

View File

@@ -320,12 +320,19 @@ static int
try_lock(int fd, bool block) try_lock(int fd, bool block)
{ {
struct flock l; struct flock l;
int error;
memset(&l, 0, sizeof l); memset(&l, 0, sizeof l);
l.l_type = F_WRLCK; l.l_type = F_WRLCK;
l.l_whence = SEEK_SET; l.l_whence = SEEK_SET;
l.l_start = 0; l.l_start = 0;
l.l_len = 0; l.l_len = 0;
return fcntl(fd, block ? F_SETLKW : F_SETLK, &l) == -1 ? errno : 0;
time_disable_restart();
error = fcntl(fd, block ? F_SETLKW : F_SETLK, &l) == -1 ? errno : 0;
time_enable_restart();
return error;
} }
/* Locks the configuration file against modification by other processes and /* Locks the configuration file against modification by other processes and

View File

@@ -44,6 +44,7 @@ static struct timeval now;
static time_t deadline = TIME_MIN; static time_t deadline = TIME_MIN;
static void setup_timer(void); static void setup_timer(void);
static void setup_signal(int flags);
static void sigalrm_handler(int); static void sigalrm_handler(int);
static void refresh_if_ticked(void); static void refresh_if_ticked(void);
static time_t time_add(time_t, time_t); static time_t time_add(time_t, time_t);
@@ -56,7 +57,6 @@ static void log_poll_interval(long long int last_wakeup,
void void
time_init(void) time_init(void)
{ {
struct sigaction sa;
if (inited) { if (inited) {
return; return;
} }
@@ -67,17 +67,49 @@ time_init(void)
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
tick = false; tick = false;
/* Set up signal handler. */ setup_signal(SA_RESTART);
setup_timer();
}
static void
setup_signal(int flags)
{
struct sigaction sa;
memset(&sa, 0, sizeof sa); memset(&sa, 0, sizeof sa);
sa.sa_handler = sigalrm_handler; sa.sa_handler = sigalrm_handler;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; sa.sa_flags = flags;
if (sigaction(SIGALRM, &sa, NULL)) { if (sigaction(SIGALRM, &sa, NULL)) {
ovs_fatal(errno, "sigaction(SIGALRM) failed"); ovs_fatal(errno, "sigaction(SIGALRM) failed");
} }
}
/* Set up periodic signal. */ /* Remove SA_RESTART from the flags for SIGALRM, so that any system call that
setup_timer(); * is interrupted by the periodic timer interrupt will return EINTR instead of
* continuing after the signal handler returns.
*
* time_disable_restart() and time_enable_restart() may be usefully wrapped
* around function calls that might otherwise block forever unless interrupted
* by a signal, e.g.:
*
* time_disable_restart();
* fcntl(fd, F_SETLKW, &lock);
* time_enable_restart();
*/
void
time_disable_restart(void)
{
setup_signal(0);
}
/* Add SA_RESTART to the flags for SIGALRM, so that any system call that
* is interrupted by the periodic timer interrupt will continue after the
* signal handler returns instead of returning EINTR. */
void
time_enable_restart(void)
{
setup_signal(SA_RESTART);
} }
static void static void

View File

@@ -41,6 +41,8 @@ BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t));
#define TIME_UPDATE_INTERVAL 100 #define TIME_UPDATE_INTERVAL 100
void time_init(void); void time_init(void);
void time_disable_restart(void);
void time_enable_restart(void);
void time_postfork(void); void time_postfork(void);
void time_refresh(void); void time_refresh(void);
time_t time_now(void); time_t time_now(void);