try_lock(int fd, bool block)
{
struct flock l;
+ int error;
+
memset(&l, 0, sizeof l);
l.l_type = F_WRLCK;
l.l_whence = SEEK_SET;
l.l_start = 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
static time_t deadline = TIME_MIN;
static void setup_timer(void);
+static void setup_signal(int flags);
static void sigalrm_handler(int);
static void refresh_if_ticked(void);
static time_t time_add(time_t, time_t);
void
time_init(void)
{
- struct sigaction sa;
if (inited) {
return;
}
gettimeofday(&now, NULL);
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);
sa.sa_handler = sigalrm_handler;
sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
+ sa.sa_flags = flags;
if (sigaction(SIGALRM, &sa, NULL)) {
ovs_fatal(errno, "sigaction(SIGALRM) failed");
}
+}
- /* Set up periodic signal. */
- setup_timer();
+/* Remove SA_RESTART from the flags for SIGALRM, so that any system call that
+ * 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