X-Git-Url: https://git.jankratochvil.net/?p=inetdmx.git;a=blobdiff_plain;f=inetdmx.c;fp=inetdmx.c;h=9e4ef8f14783fc0e5bb077fe218471b7363cce67;hp=99077b9c2e0485cd174dee4bb7b7272bea162c35;hb=e2834a61ec57167274fbb21a23244aba61cddc6c;hpb=bc336bd45448b5761967792c416d56f84536e95a diff --git a/inetdmx.c b/inetdmx.c index 99077b9..9e4ef8f 100644 --- 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();