Attempt for simplified '--stop' locking.
[inetdmx.git] / inetdmx.c
index 99077b9..9e4ef8f 100644 (file)
--- a/inetdmx.c
+++ b/inetdmx.c
@@ -210,21 +210,35 @@ static void sighandler_flock_timeout(int signo)
        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);
@@ -235,7 +249,7 @@ retry:
                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)) {
@@ -246,7 +260,7 @@ retry:
                lock_fd=-1;
                goto retry;
                }
-       return 1;
+       return LOCK_CREATE_MYSELF_LOCKED;
 }
 
 static void lock_touch(void)
@@ -470,24 +484,17 @@ int retry;
                        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)
@@ -498,10 +505,22 @@ 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)
@@ -511,12 +530,10 @@ int is_fresh;
        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();