Hi List,

attched patch should fix race conditions in the accesslog and log module while 
reopening from log files. Patch just add reader/writer lock and make sure 
that writer are locked while log files will be reopened plus adds 
log_shutdown(..) function in order to proper close log files.

Comments and votes are highly welcome!

-- 
Best regards / Mit besten Gr��en aus D�sseldorf

Dipl.-Ing.
Alexander Malysh
___________________________________________

Centrium GmbH
Vogelsanger Weg 80
40470 D�sseldorf

Fon: +49 (0211) 74 84 51 80
Fax: +49 (0211) 277 49 109

email: [EMAIL PROTECTED]
web: www.centrium.de
msn: [EMAIL PROTECTED]
icq: 98063111
___________________________________________

Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
Index: gwlib/log.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/log.h,v
retrieving revision 1.17
diff -a -u -r1.17 log.h
--- gwlib/log.h	4 Mar 2003 15:16:09 -0000	1.17
+++ gwlib/log.h	14 Oct 2003 13:26:17 -0000
@@ -30,6 +30,9 @@
 /* Initialize the log file module */
 void log_init();
 
+/* Shutdown the log file module */
+void log_shutdown();
+
 /* Print a panicky error message and terminate the program with a failure.
  * So, this function is called when there is no other choice than to exit
  * immediately, with given reason
Index: gwlib/log.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/log.c,v
retrieving revision 1.38
diff -a -u -r1.38 log.c
--- gwlib/log.c	29 Aug 2003 17:29:58 -0000	1.38
+++ gwlib/log.c	14 Oct 2003 13:26:17 -0000
@@ -49,7 +49,7 @@
 static int num_logfiles = 0;
 
 
-/* 
+/*
  * Mapping array between thread id and logfiles[] index.
  * This is used for smsc specific logging.
  */
@@ -74,6 +74,11 @@
 
 
 /*
+ * Reopen/rotate locking things.
+ */
+static List *writers = NULL;
+
+/*
  * Syslog support.
  */
 static int sysloglevel;
@@ -83,10 +88,10 @@
 /*
  * Make sure stderr is included in the list.
  */
-static void add_stderr(void) 
+static void add_stderr(void)
 {
     int i;
-    
+
     for (i = 0; i < num_logfiles; ++i)
 	if (logfiles[i].file == stderr)
 	    return;
@@ -105,14 +110,25 @@
     for (i = 0; i <= THREADTABLE_SIZE; i++) {
         thread_to[i] = 0;
     }
+
+    add_stderr();
+
+    /* initialize rw lock */
+    writers = list_create();
+}
+
+void log_shutdown()
+{
+    log_close_all();
+    list_destroy(writers, NULL);
+    writers = NULL;
 }
 
 
-void log_set_output_level(enum output_level level) 
+void log_set_output_level(enum output_level level)
 {
     int i;
-    
-    add_stderr();
+
     for (i = 0; i < num_logfiles; ++i) {
 	if (logfiles[i].file == stderr) {
 	    logfiles[i].minimum_output_level = level;
@@ -121,10 +137,10 @@
     }
 }
 
-void log_set_log_level(enum output_level level) 
+void log_set_log_level(enum output_level level)
 {
     int i;
-    
+
     /* change everything but stderr */
     for (i = 0; i < num_logfiles; ++i) {
         if (logfiles[i].file != stderr) {
@@ -135,7 +151,7 @@
 }
 
 
-void log_set_syslog(const char *ident, int syslog_level) 
+void log_set_syslog(const char *ident, int syslog_level)
 {
     if (ident == NULL)
 	dosyslog = 0;
@@ -148,18 +164,25 @@
 }
 
 
-void log_reopen(void) 
+void log_reopen(void)
 {
-	int i, j, found;
-	
+    int i, j, found;
+
+    /*
+     * Writer lock.
+     */
+    list_lock(writers);
+    /* wait for writers complete */
+    list_consume(writers);
+
     for (i = 0; i < num_logfiles; ++i) {
         if (logfiles[i].file != stderr) {
             found = 0;
 
-            /* 
+            /*
              * Reverse seek for allready reopened logfile.
              * If we find a previous file descriptor for the same file
-             * name, then don't reopen that duplicate, but assign the 
+             * name, then don't reopen that duplicate, but assign the
              * file pointer to it.
              */
             for (j = i-1; j >= 0 && found == 0; j--) {
@@ -178,40 +201,59 @@
                       logfiles[i].filename);
             }
         }
-    }		
+    }
+
+    /*
+     * Unlock writer.
+     */
+    list_unlock(writers);
 }
 
 
-void log_close_all(void) 
+void log_close_all(void)
 {
+    /*
+     * Writer lock.
+     */
+    list_lock(writers);
+    /* wait for writers */
+    list_consume(writers);
+
     while (num_logfiles > 0) {
         --num_logfiles;
-        if (logfiles[num_logfiles].file != stderr && 
+        if (logfiles[num_logfiles].file != stderr &&
             logfiles[num_logfiles].file != NULL)
             fclose(logfiles[num_logfiles].file);
         logfiles[num_logfiles].file = NULL;
     }
+
+    /*
+     * Unlock writer.
+     */
+    list_unlock(writers);
 }
 
 
-int log_open(char *filename, int level, enum excl_state excl) 
+int log_open(char *filename, int level, enum excl_state excl)
 {
     FILE *f = NULL;
     int i;
     
-    add_stderr();
+    if (writers == NULL)
+        writers = list_create();
+
     if (num_logfiles == MAX_LOGFILES) {
-        error(0, "Too many log files already open, not adding `%s'", 
+        error(0, "Too many log files already open, not adding `%s'",
               filename);
         return -1;
     }
-    
+
     if (strlen(filename) > FILENAME_MAX) {
         error(0, "Log filename too long: `%s'.", filename);
         return -1;
     }
-    
-    /* 
+
+    /*
      * Check if the file is already opened for logging.
      * If there is an open file, then assign the file descriptor
      * that is already existing for this log file.
@@ -356,17 +398,20 @@
 	    char buf[FORMAT_SIZE]; \
 	    va_list args; \
 	    \
-	    add_stderr(); \
 	    format(buf, level, place, err, fmt); \
+            list_lock(writers); \
+            list_add_producer(writers); \
+            list_unlock(writers); \
 	    for (i = 0; i < num_logfiles; ++i) { \
 		if (logfiles[i].exclusive == GW_NON_EXCL && \
-            level >= logfiles[i].minimum_output_level && \
-            logfiles[i].file != NULL) { \
-		    va_start(args, fmt); \
-		    output(logfiles[i].file, buf, args); \
-		    va_end(args); \
+                    level >= logfiles[i].minimum_output_level && \
+                    logfiles[i].file != NULL) { \
+		        va_start(args, fmt); \
+		        output(logfiles[i].file, buf, args); \
+		        va_end(args); \
 		} \
 	    } \
+            list_remove_producer(writers); \
 	    if (dosyslog) { \
 		va_start(args, fmt); \
 		kannel_syslog(buf,args,level); \
@@ -379,25 +424,31 @@
 	    char buf[FORMAT_SIZE]; \
 	    va_list args; \
 	    \
-	    add_stderr(); \
 	    format(buf, level, place, err, fmt); \
-        if (logfiles[e].exclusive == GW_EXCL && \
-            level >= logfiles[e].minimum_output_level && \
-            logfiles[e].file != NULL) { \
-            va_start(args, fmt); \
-            output(logfiles[e].file, buf, args); \
-            va_end(args); \
-        } \
+            list_lock(writers); \
+            list_add_producer(writers); \
+            list_unlock(writers); \
+            if (logfiles[e].exclusive == GW_EXCL && \
+                level >= logfiles[e].minimum_output_level && \
+                logfiles[e].file != NULL) { \
+                va_start(args, fmt); \
+                output(logfiles[e].file, buf, args); \
+                va_end(args); \
+            } \
+            list_remove_producer(writers); \
 	} while (0)
 
 
-void gw_panic(int err, const char *fmt, ...) 
+void gw_panic(int err, const char *fmt, ...)
 {
     /* 
      * we don't want PANICs to spread accross smsc logs, so
      * this will be always within the main core log.
      */
     FUNCTION_GUTS(GW_PANIC, "");
+#ifdef SEGFAULT_PANIC
+    *((char*)0) = 0;
+#endif
     exit(EXIT_FAILURE);
 }
 
Index: gwlib/gwlib.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/gwlib.c,v
retrieving revision 1.14
diff -a -u -r1.14 gwlib.c
--- gwlib/gwlib.c	4 Mar 2003 15:16:09 -0000	1.14
+++ gwlib/gwlib.c	14 Oct 2003 13:26:17 -0000
@@ -44,5 +44,6 @@
     gw_check_leaks();
     gwmem_shutdown();
     gwlib_protected_shutdown();
+    log_shutdown();
     init = 0;
 }
Index: gwlib/accesslog.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/accesslog.c,v
retrieving revision 1.2
diff -a -u -r1.2 accesslog.c
--- gwlib/accesslog.c	22 Jan 2001 12:23:43 -0000	1.2
+++ gwlib/accesslog.c	14 Oct 2003 13:26:17 -0000
@@ -21,28 +21,48 @@
 
 static int use_localtime;
 
+/*
+ * Reopen/rotate lock.
+ */
+static List *writers = NULL;
+
 void alog_reopen(void)
 {
     if (file == NULL)
 	return;
-    
+
     alog("Log ends");
+
+    list_lock(writers);
+    /* wait for writers to complete */
+    list_consume(writers);
+
     fclose(file);
     file = fopen(filename, "a");
+
+    list_unlock(writers);
+
     if (file == NULL) {
 	error(errno, "Couldn't re-open access logfile `%s'.",
 	      filename);
-    } else	
+    } else
 	alog("Log begins");
 }
 
 
 void alog_close(void)
 {
+
     if (file != NULL) {
 	alog("Log ends");
+        list_lock(writers);
+        /* wait for writers to complete */
+        list_consume(writers);
 	fclose(file);
 	file = NULL;
+        list_unlock(writers);
+        list_destroy(writers, NULL);
+        writers = NULL;
     }
 }
 
@@ -59,6 +79,10 @@
 	error(0, "Access Log filename too long: `%s', cannot open.", fname);
 	return;
     }
+
+    if (writers == NULL)
+        writers = list_create();
+
     f = fopen(fname, "a");
     if (f == NULL) {
 	error(errno, "Couldn't open logfile `%s'.", fname);
@@ -120,8 +144,16 @@
     buf = gw_malloc(FORMAT_SIZE + 1);
     format(buf, fmt);
     va_start(args, fmt);
+
+    list_lock(writers);
+    list_add_producer(writers);
+    list_unlock(writers);
+
     vfprintf(file, buf, args);
     fflush(file);
+
+    list_remove_producer(writers);
+
     va_end(args);
     gw_free(buf);
 }

Reply via email to