util: Handle serverLogMutex lock across forks
[openafs.git] / src / util / serverLog.c
index bfb2803..60e8517 100644 (file)
@@ -12,7 +12,7 @@
 /*  Information Technology Center                                         */
 /*  Date: 05/21/97                                                        */
 /*                                                                        */
-/*  Function    - These routiens implement logging from the servers       */
+/*  Function    - These routines implement logging from the servers.      */
 /*                                                                        */
 /* ********************************************************************** */
 
@@ -25,7 +25,6 @@
 #include <roken.h>             /* Must come after procmgmt.h */
 #ifdef AFS_PTHREAD_ENV
  #include <opr/softsig.h>
- #include <afs/procmgmt_softsig.h>     /* Must come after softsig.h */
 #endif
 #include <afs/opr.h>
 #include "afsutil.h"
@@ -55,6 +54,9 @@ static pthread_mutex_t serverLogMutex;
 #define O_NONBLOCK 0
 #endif
 
+/*!
+ * Placeholder function to return dummy thread number.
+ */
 static int
 dummyThreadNum(void)
 {
@@ -64,13 +66,13 @@ static int (*threadNumProgram) (void) = dummyThreadNum;
 
 /* After single-threaded startup, accesses to serverlogFD and
  * serverLogSyslog* are protected by LOCK_SERVERLOG(). */
-static int serverLogFD = -1;
-static struct logOptions serverLogOpts;
+static int serverLogFD = -1;   /*!< The log file descriptor. */
+static struct logOptions serverLogOpts;        /*!< logging options */
 
-int LogLevel;
-static int threadIdLogs = 0;
-static int resetSignals = 0;
-static char *ourName = NULL;
+int LogLevel;                  /*!< The current logging level. */
+static int threadIdLogs = 0;   /*!< Include the thread id in log messages when true. */
+static int resetSignals = 0;   /*!< Reset signal handlers for the next signal when true. */
+static char *ourName = NULL;   /*!< The fully qualified log file path, saved for reopens. */
 
 static int OpenLogFile(const char *fileName);
 static void RotateLogFile(void);
@@ -123,29 +125,51 @@ GetLogFilename(void)
     return serverLogOpts.lopt_dest == logDest_file ? (const char*)ourName : "";
 }
 
+/*!
+ * Set the function to log thread numbers.
+ */
 void
 SetLogThreadNumProgram(int (*func) (void) )
 {
     threadNumProgram = func;
 }
 
+/*!
+ * Write a block of bytes to the log.
+ *
+ * Write a block of bytes directly to the log without formatting
+ * or prepending a timestamp.
+ *
+ * \param[in] buf  pointer to bytes to write
+ * \param[in] len  number of bytes to write
+ */
 void
 WriteLogBuffer(char *buf, afs_uint32 len)
 {
     LOCK_SERVERLOG();
     if (serverLogFD >= 0) {
-       if (write(serverLogFD, buf, len) < 0)
-           ; /* don't care */
+       if (write(serverLogFD, buf, len) < 0) {
+           /* don't care */
+        }
     }
     UNLOCK_SERVERLOG();
 }
 
+/*!
+ * Get the current thread number.
+ */
 int
 LogThreadNum(void)
 {
   return (*threadNumProgram) ();
 }
 
+/*!
+ * Write a message to the log.
+ *
+ * \param[in] format  printf-style format string
+ * \param[in] args    variable list of arguments
+ */
 void
 vFSLog(const char *format, va_list args)
 {
@@ -180,8 +204,9 @@ vFSLog(const char *format, va_list args)
     } else
 #endif
     if (serverLogFD >= 0) {
-       if (write(serverLogFD, tbuffer, len) < 0)
-           ; /* don't care */
+       if (write(serverLogFD, tbuffer, len) < 0) {
+           /* don't care */
+        }
     }
     UNLOCK_SERVERLOG();
 
@@ -193,8 +218,12 @@ vFSLog(const char *format, va_list args)
 #endif
 }                              /*vFSLog */
 
-/* VARARGS1 */
-/*@printflike@*/
+/*!
+ * Write a message to the log.
+ *
+ * \param[in] format  printf-style format specification
+ * \param[in] ...     arguments for format specification
+ */
 void
 FSLog(const char *format, ...)
 {
@@ -205,6 +234,16 @@ FSLog(const char *format, ...)
     va_end(args);
 }                              /*FSLog */
 
+/*!
+ * Write the command-line invocation to the log.
+ *
+ * \param[in] argc      argument count from main()
+ * \param[in] argv      argument vector from main()
+ * \param[in] progname  program name
+ * \param[in] version   program version
+ * \param[in] logstring log message string
+ * \param[in] log       printf-style log function
+ */
 void
 LogCommandLine(int argc, char **argv, const char *progname,
               const char *version, const char *logstring,
@@ -234,6 +273,9 @@ LogCommandLine(int argc, char **argv, const char *progname,
     }
 }
 
+/*!
+ * Write the single-DES deprecation warning to the log.
+ */
 void
 LogDesWarning(void)
 {
@@ -308,6 +350,13 @@ RenameLogFile(const char *fileName)
     }
 }
 
+/*!
+ * Write message to the log to indicate the log level.
+ *
+ * This helper function is called by the signal handlers when the log level is
+ * changed, to write a message to the log to indicate the log level has been
+ * changed.
+ */
 static void*
 DebugOn(void *param)
 {
@@ -320,8 +369,15 @@ DebugOn(void *param)
     return 0;
 }                              /*DebugOn */
 
-
-
+/*!
+ * Signal handler to increase the logging level.
+ *
+ * Increase the current logging level to 1 if it in currently 0,
+ * otherwise, increase the current logging level by a factor of 5 if it
+ * is currently non-zero.
+ *
+ * Enables thread id logging when the log level is greater than 1.
+ */
 void
 SetDebug_Signal(int signo)
 {
@@ -355,6 +411,14 @@ SetDebug_Signal(int signo)
     }
 }                              /*SetDebug_Signal */
 
+/*!
+ * Signal handler to reset the logging level.
+ *
+ * Reset the logging level and disable thread id logging.
+ *
+ * \note This handler has the side-effect of rotating and reopening
+ *       MR-AFS style logs.
+ */
 void
 ResetDebug_Signal(int signo)
 {
@@ -380,6 +444,29 @@ ResetDebug_Signal(int signo)
     }
 }                              /*ResetDebug_Signal */
 
+/*!
+ * Handle requests to reopen the log.
+ *
+ * This signal handler will reopen the log file. A new, empty log file
+ * will be created if the log file does not already exist.
+ *
+ * External log rotation programs may rotate a server log file by
+ * renaming the existing server log file and then immediately sending a
+ * signal to the corresponding server process.  Server log messages will
+ * continue to be appended to the renamed server log file until the
+ * server log is reopened.  After this signal handler completes, server
+ * log messages will be written to the new log file.  This allows
+ * external log rotation programs to rotate log files without
+ * messages being dropped.
+ */
+void
+ReOpenLog_Signal(int signo)
+{
+    ReOpenLog();
+    if (resetSignals) {
+       (void)signal(signo, ReOpenLog_Signal);
+    }
+}
 
 #ifdef AFS_PTHREAD_ENV
 /*!
@@ -392,6 +479,7 @@ SetupLogSoftSignals(void)
 {
     opr_softsig_Register(SIGHUP, ResetDebug_Signal);
     opr_softsig_Register(SIGTSTP, SetDebug_Signal);
+    opr_softsig_Register(SIGUSR1, ReOpenLog_Signal);
 #ifndef AFS_NT40_ENV
     (void)signal(SIGPIPE, SIG_IGN);
 #endif
@@ -411,8 +499,8 @@ SetupLogSignals(void)
 {
     resetSignals = 1;
     (void)signal(SIGHUP, ResetDebug_Signal);
-    /* Note that we cannot use SIGUSR1 -- Linux stole it for pthreads! */
     (void)signal(SIGTSTP, SetDebug_Signal);
+    (void)signal(SIGUSR1, ReOpenLog_Signal);
 #ifndef AFS_NT40_ENV
     (void)signal(SIGPIPE, SIG_IGN);
 #endif
@@ -420,9 +508,24 @@ SetupLogSignals(void)
 
 #if defined(AFS_PTHREAD_ENV)
 static void
+LockServerLog(void)
+{
+    LOCK_SERVERLOG();
+}
+
+static void
+UnlockServerLog(void)
+{
+    UNLOCK_SERVERLOG();
+}
+
+static void
 InitServerLogMutex(void)
 {
     opr_Verify(pthread_mutex_init(&serverLogMutex, NULL) == 0);
+# ifndef AFS_NT40_ENV
+    opr_Verify(pthread_atfork(LockServerLog, UnlockServerLog, UnlockServerLog) == 0);
+# endif
 }
 #endif /* AFS_PTHREAD_ENV */
 
@@ -436,8 +539,9 @@ InitServerLogMutex(void)
 static void
 RedirectStdStreams(const char *fileName)
 {
-    if (freopen(fileName, "a", stdout) == NULL)
-       ; /* don't care */
+    if (freopen(fileName, "a", stdout) == NULL) {
+       /* don't care */
+    }
     if (freopen(fileName, "a", stderr) != NULL) {
 #ifdef HAVE_SETVBUF
        setvbuf(stderr, NULL, _IONBF, 0);
@@ -485,9 +589,12 @@ OpenLogFile(const char *fileName)
     RedirectStdStreams(fileName);
 
     /* Save our name for reopening. */
-    free(ourName);
-    ourName = strdup(fileName);
-    opr_Assert(ourName != NULL);
+    if (ourName != fileName) {
+       /* Make a copy if needed */
+       free(ourName);
+       ourName = strdup(fileName);
+       opr_Assert(ourName != NULL);
+    }
 
     serverLogFD = tempfd;