sighandler_flock_timeout_hit=1;
}
-static int lock_create(int lock_mode)
+enum lock_create_rc {
+ LOCK_CREATE_NO_LOCK_FILENAME,
+ LOCK_CREATE_FILE_NOT_FOUND, /* only if: lock_mode&LOCK_NB */
+ LOCK_CREATE_ALREADY_LOCKED, /* only if: lock_mode&LOCK_NB */
+ LOCK_CREATE_MYSELF_LOCKED, /* only for: lock_create() */
+ LOCK_CREATE_MYSELF_LOCKED_AND_FRESH, /* only for: lock_open_and_time_check() */
+ LOCK_CREATE_MYSELF_LOCKED_AND_STALE, /* only for: lock_open_and_time_check() */
+ };
+/* It will never create the lock file if: lock_mode&LOCK_NB */
+static enum lock_create_rc lock_create(int lock_mode)
{
int retries=3;
sighandler_t sighandler_alrm_orig;
int flock_rc;
if (!opt_lock)
- return 1;
+ return LOCK_CREATE_NO_LOCK_FILENAME;
/* Never drop the lock if the lock is already being held. */
if (lock_fd!=-1)
retries=-1;
retry:
if (lock_fd==-1) {
- if (-1==(lock_fd=open(opt_lock,O_CREAT|O_RDWR,0600)))
+ if (-1==(lock_fd=open(opt_lock,
+ O_RDWR | (lock_mode&LOCK_NB ? 0 : O_CREAT),
+ 0600))) {
+ if (errno==ENOENT && lock_mode&LOCK_NB)
+ return LOCK_CREATE_FILE_NOT_FOUND;
fatal("Error creating lock file \"%s\": %m",opt_lock);
+ }
}
sighandler_alrm_orig=signal(SIGALRM,sighandler_flock_timeout);
alarm(opt_start_command_timeout+FLOCK_TIMEOUT_OVER_START_TIMEOUT);
fatal("Timeout locking lock file \"%s\": %m",opt_lock);
if (flock_rc) {
if (lock_mode&LOCK_NB && errno==EWOULDBLOCK)
- return 0;
+ return LOCK_CREATE_ALREADY_LOCKED;
fatal("Error locking lock file \"%s\": %m",opt_lock);
}
if (access(opt_lock,R_OK|W_OK)) {
lock_fd=-1;
goto retry;
}
- return 1;
+ return LOCK_CREATE_MYSELF_LOCKED;
}
static void lock_touch(void)
opt_start_command_timeout,opt_port,opt_command);
}
-/* Returns: Is fresh or does not exist? */
-static int lock_open_and_time_check(int lock_mode)
+static enum lock_create_rc lock_open_and_time_check(int lock_mode)
{
+enum lock_create_rc rc;
struct stat statbuf;
- if (!opt_lock)
- return 0;
-
- if (access(opt_lock,R_OK|W_OK)) {
- if (errno==ENOENT)
- return 1;
- fatal("Error checking existance of the lock file \"%s\": %m",opt_lock);
- }
- if (!lock_create(lock_mode|LOCK_NB))
- return 0;
+ if (LOCK_CREATE_MYSELF_LOCKED!=(rc=lock_create(lock_mode|LOCK_NB)))
+ return rc;
if (lock_fd==-1 || fstat(lock_fd,&statbuf))
fatal("Error fstat(2)ting lock file \"%s\": %m",opt_lock);
- return statbuf.st_mtime>=time(NULL)-opt_idle_server_timeout;
+ return (statbuf.st_mtime>=time(NULL)-opt_idle_server_timeout
+ ? LOCK_CREATE_MYSELF_LOCKED_AND_FRESH : LOCK_CREATE_MYSELF_LOCKED_AND_STALE);
}
static void lock_delete_and_close(void)
lock_close();
}
+static void lock_open_and_return_if_stale(int lock_mode)
+{
+ switch (lock_open_and_time_check(lock_mode)) {
+ case LOCK_CREATE_NO_LOCK_FILENAME: return;
+ case LOCK_CREATE_FILE_NOT_FOUND: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_ALREADY_LOCKED: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_MYSELF_LOCKED: assert(0);
+ case LOCK_CREATE_MYSELF_LOCKED_AND_FRESH: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_MYSELF_LOCKED_AND_STALE: return;
+ }
+ assert(0);
+}
+
static void stop(void) G_GNUC_NORETURN;
static void stop(void)
{
-int is_fresh;
/* Lock still being held! */
if (opt_port)
if (opt_idle_server_timeout!=DEFAULT_IDLE_SERVER_TIMEOUT && !opt_lock)
fatal("-l|--lock is a required argument for -i|--idle-server-timeout of -1|--start");
- is_fresh=lock_open_and_time_check(LOCK_SH);
+ lock_open_and_return_if_stale(LOCK_SH);
lock_close();
- if (is_fresh)
- exit(EXIT_SUCCESS);
- lock_open_and_time_check(LOCK_EX);
+ lock_open_and_return_if_stale(LOCK_EX);
system_checked(opt_command);
lock_delete_and_close();