Some prevention of stale locks by unlocking it whenever possible.
[inetdmx.git] / inetdmx.c
index ebab3bf..006a4f2 100644 (file)
--- a/inetdmx.c
+++ b/inetdmx.c
@@ -72,11 +72,14 @@ static int opt_syslog;
 static int opt_stderr;
 static const char *opt_lock;
 static int opt_ignore_spawned_command_output;
-static const char *opt_command;
+static char *opt_command;
 
 
 static void fatal(const char *fmt,...) G_GNUC_PRINTF(1,2) G_GNUC_NORETURN;
 
+/* for atexit(3) function */
+static int verror_quiet;
+
 static void verror(const char *fmt,va_list ap) G_GNUC_PRINTF(1,0);
 static void verror(const char *fmt,va_list ap)
 {
@@ -84,6 +87,8 @@ int use_syslog=opt_syslog,use_stderr=opt_stderr;
 char *string;
 const char *const double_error="Error printing error message";
 
+       if (verror_quiet)
+               return;
        if (!use_syslog && !use_stderr)
                use_stderr=1;
        if (-1==vasprintf(&string,fmt,ap)) {
@@ -135,6 +140,15 @@ int rc;
        return string;
 }
 
+static void *xmalloc(size_t size)
+{
+void *r;
+
+       if ((r=malloc(size)))
+               return r;
+       fatal("Error allocing %lu bytes",(unsigned long)size);
+}
+
 static void usage(void)
 {
        fprintf(stderr,"\
@@ -228,13 +242,25 @@ static void lock_touch(void)
 
 static void lock_close(void)
 {
-       if (lock_fd==-1)
+       if (lock_fd==-1 || !opt_lock)
                return;
+       /* It should not be needed but some stale locks were seen on:
+        *      White Box Linux kernel-smp-2.6.9-5.0.5.EL
+        */
+       if (flock(lock_fd,LOCK_UN|LOCK_NB))
+               fatal("Error unlocking lock file \"%s\": %m",opt_lock);
        if (close(lock_fd))
                fatal("Error closing lock file \"%s\": %m",opt_lock);
        lock_fd=-1;
 }
 
+static void lock_close_atexit(void)
+{
+       /* Prevent some crashes of malloc(3) etc. */
+       verror_quiet=1;
+       lock_close();
+}
+
 static int connect_try(void)
 {
 int fdtcp;
@@ -276,13 +302,6 @@ int fdi,fdo;
        pollfdi_name[0]=conn0_name;
        pollfdi_name[1]=conn1_name;
        for (;;) {
-               for (fdi=0;fdi<G_N_ELEMENTS(pollfdi);fdi++)
-                       if (pollfdi[fdi].events)
-                               break;
-               if (fdi>=G_N_ELEMENTS(pollfdi)) {
-                       lock_close();
-                       exit(EXIT_SUCCESS);
-                       }
                if (0>=poll(pollfdi,G_N_ELEMENTS(pollfdi),-1))
                        fatal("poll(%s socket,%s socket): %m",pollfdi_name[0],pollfdi_name[1]);
                for (fdi=0;fdi<G_N_ELEMENTS(pollfdi);fdi++)
@@ -307,8 +326,8 @@ int fdi,fdo;
                                        fatal("read(%s socket): %m",pollfdi_name[fdi]);
                                        }
                                if (got==0) {
-                                       pollfdi[fdi].events&=~POLLIN;
-                                       break;
+                                       lock_close();
+                                       exit(EXIT_SUCCESS);
                                        }
                                for (fdo=0;fdo<G_N_ELEMENTS(pollfdi);fdo++) {
                                        if (fdi==fdo)
@@ -486,12 +505,17 @@ int main(int argc,char **argv) G_GNUC_NORETURN;
 int main(int argc,char **argv)
 {
 char optc;
+size_t opt_command_len;
+int i;
+char *s;
 
        if ((program_name=strrchr(argv[0],'/')))
                program_name++;
        else
                program_name=argv[0];
 
+       atexit(lock_close_atexit);
+
        optarg=NULL; optind=0;  /* FIXME: Possible portability problem. */
        while ((optc=getopt_long(argc,argv,"01T:i:Sel:p:Ih",longopts,NULL))!=EOF) switch (optc) {
 long l;
@@ -556,9 +580,21 @@ char *endptr;
 
        if (optind>=argc)
                fatal("<start-server-command/stop-server-command> is a required argument");
-       if (optind+1<argc)
-               fatal("Too many arguments, <start-server-command/stop-server-command> may need quoting");
-       opt_command=argv[optind];
+       opt_command_len=0;
+       for (i=optind;i<argc;i++)
+               opt_command_len+=strlen(argv[i])+1;
+       opt_command=xmalloc(opt_command_len);
+       s=opt_command;
+       for (i=optind;i<argc;i++) {
+size_t argv_i_len=strlen(argv[i]);
+
+               if (s>opt_command)
+                       *s++=' ';
+               memcpy(s,argv[i],argv_i_len);
+               s+=argv_i_len;
+               }
+       *s++=0;
+       assert(s==opt_command+opt_command_len);
 
        if (!opt_syslog && !opt_stderr)
                opt_stderr=1;