[Fedora-directory-commits] ldapserver/ldap/servers/slapd log.c, 1.17, 1.18 libglobs.c, 1.21, 1.22

Noriko Hosoi (nhosoi) fedora-directory-commits at redhat.com
Fri Oct 5 17:00:06 UTC 2007


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv1833

Modified Files:
	log.c libglobs.c 
Log Message:
Resolves: #173873
Summary: Directory Server should shutdown if it fails to write logs (comment #7)
Change Description:
1. introduced a new static function log__error_emergency, which is called at
emergency to log to the syslog and at least try to log into the errors log one
more time.
2. added an error parameter to the macro LOG_WRITE_NOW to return if the writing
to the log was successful or not.
3. if opening an errors log or writing to an errors log failed, call
g_set_shutdown to shutdown the server gracefully.
4. log__error_emergency calls writing log function (LDAPDebug --> slapd_log_error_proc_internal) with ERROR_LOCK_WRITE unlocked, if locked. 



Index: log.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/log.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- log.c	3 Oct 2007 20:17:22 -0000	1.17
+++ log.c	5 Oct 2007 17:00:04 -0000	1.18
@@ -126,7 +126,7 @@
 static int 	log__getfilesize(LOGFD fp);
 static int 	log__enough_freespace(char  *path);
 
-static int 	vslapd_log_error(LOGFD fp, char *subsystem, char *fmt, va_list ap );
+static int 	vslapd_log_error(LOGFD fp, char *subsystem, char *fmt, va_list ap, int locked );
 static int 	vslapd_log_access(char *fmt, va_list ap );
 static void	log_convert_time (time_t ctime, char *tbuf, int type);
 static time_t	log_reverse_convert_time (char *tbuf);
@@ -134,7 +134,7 @@
 static void	log_append_buffer2(time_t tnl, LogBufferInfo *lbi, char *msg1, size_t size1, char *msg2, size_t size2);
 static void	log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now);
 static void	log_write_title(LOGFD fp);
-
+static void log__error_emergency(const char *errstr, int reopen, int locked);
 
 static int
 slapd_log_error_proc_internal(
@@ -154,8 +154,8 @@
  * LOG_OPEN_WRITE(fd, filename, mode) is the same but truncates the file and
  *	starts writing at the beginning of the file.
  * LOG_WRITE(fd, buffer, size, headersize) writes into a LOGFD
- * LOG_WRITE_NOW(fd, buffer, size, headersize) writes into a LOGFD and flushes the
- *	buffer if necessary
+ * LOG_WRITE_NOW(fd, buffer, size, headersize, err) writes into a LOGFD and 
+ *  flushes the buffer if necessary
  * LOG_CLOSE(fd) closes the logfile
  */
 #ifdef XP_WIN32
@@ -168,10 +168,12 @@
 	{\
 		ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_FAILED_TO_WRITE_LOG, 1, (buffer)); \
 	}
-#define LOG_WRITE_NOW(fd, buffer, size, headersize) do {\
+#define LOG_WRITE_NOW(fd, buffer, size, headersize, err) do {\
+		(err) = 0; \
 		if ( fwrite((buffer), (size), 1, (fd)) != 1 ) \
 		{ \
 			ReportSlapdEvent(EVENTLOG_INFORMATION_TYPE, MSG_SERVER_FAILED_TO_WRITE_LOG, 1, (buffer)); \
+			(err) = 1; \
 		}; \
 		fflush((fd)); \
 	} while (0)
@@ -190,11 +192,13 @@
 		PRErrorCode prerr = PR_GetError(); \
 		syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(headersize) ); \
 	}
-#define LOG_WRITE_NOW(fd, buffer, size, headersize) do {\
+#define LOG_WRITE_NOW(fd, buffer, size, headersize, err) do {\
+	(err) = 0; \
 	if ( slapi_write_buffer((fd), (buffer), (size)) != (size) ) \
 	{ \
 		PRErrorCode prerr = PR_GetError(); \
 		syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(headersize) ); \
+		(err) = prerr; \
 	} \
 	/* Should be a flush in here ?? Yes because PR_SYNC doesn't work ! */ \
 	PR_Sync(fd); \
@@ -528,10 +532,13 @@
 
 	/* try to open the file, we may have a incorrect path */
 	if (! LOG_OPEN_APPEND(fp, pathname, loginfo.log_error_mode)) {
-		LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
-				"errno %d (%s)\n",
-				pathname, errno, slapd_system_strerror(errno));
+		char buffer[SLAPI_LOG_BUFSIZ];
+		PRErrorCode prerr = PR_GetError();
 		/* stay with the current log file */
+		PR_snprintf(buffer, sizeof(buffer),
+				"Failed to open file %s. error %d (%s). Exiting...",
+				pathname, prerr, slapd_pr_strerror(prerr));
+		log__error_emergency(buffer, 0, 0);
 		return LDAP_UNWILLING_TO_PERFORM;
 	}
 	
@@ -1589,11 +1596,12 @@
 	char *buildnum = config_get_buildnum();
 	char buff[512];
 	int bufflen = sizeof(buff);
+	int err = 0;
 
 	PR_snprintf(buff, bufflen, "\t%s B%s\n",
 				fe_cfg->versionstring ? fe_cfg->versionstring : "Fedora-Directory",
 				buildnum ? buildnum : "");
-	LOG_WRITE_NOW(fp, buff, strlen(buff), 0);
+	LOG_WRITE_NOW(fp, buff, strlen(buff), 0, err);
 
 	if (fe_cfg->localhost) {
 		PR_snprintf(buff, bufflen, "\t%s:%d (%s)\n\n",
@@ -1608,7 +1616,7 @@
 		PR_snprintf(buff, bufflen, "\t<host>:<port> (%s)\n\n",
 				fe_cfg->configdir ? fe_cfg->configdir : "");
 	}
-	LOG_WRITE_NOW(fp, buff, strlen(buff), 0);
+	LOG_WRITE_NOW(fp, buff, strlen(buff), 0, err);
 	slapi_ch_free((void **)&buildnum);
 }
 
@@ -1696,6 +1704,7 @@
 	char	*buffer,
 	int	buf_len)
 {
+	int err;
 	if ( (loginfo.log_audit_state & LOGGING_ENABLED) && (loginfo.log_audit_file != NULL) ){
 		LOG_AUDIT_LOCK_WRITE( );
 		if (log__needrotation(loginfo.log_audit_fdes,
@@ -1715,7 +1724,7 @@
 			log_write_title( loginfo.log_audit_fdes);
 			loginfo.log_audit_state &= ~LOGGING_NEED_TITLE;
 		}
-	    LOG_WRITE_NOW(loginfo.log_audit_fdes, buffer, buf_len, 0);
+	    LOG_WRITE_NOW(loginfo.log_audit_fdes, buffer, buf_len, 0, err);
    		LOG_AUDIT_UNLOCK_WRITE();
 	    return 0;
 	}
@@ -1755,6 +1764,8 @@
 					SLAPD_ERROR_LOG) == LOG_ROTATE) {
 			if (log__open_errorlogfile(LOGFILE_NEW, 1) != LOG_SUCCESS) {
 				LOG_ERROR_UNLOCK_WRITE();
+				/* shouldn't continue. error is syslog'ed in open_errorlogfile */
+				g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
 				return 0;
 			}
 			while (loginfo.log_error_rotationsyncclock <= loginfo.log_error_ctime) {
@@ -1763,19 +1774,19 @@
 		}
 
 		if (!(detached)) { 
-			rc = vslapd_log_error( NULL, subsystem, fmt, ap_err ); 
+			rc = vslapd_log_error( NULL, subsystem, fmt, ap_err, 1 ); 
 		} 
 		if ( loginfo.log_error_fdes != NULL ) { 
 			if (loginfo.log_error_state & LOGGING_NEED_TITLE) {
 				log_write_title(loginfo.log_error_fdes);
 				loginfo.log_error_state &= ~LOGGING_NEED_TITLE;
 			}
-			rc = vslapd_log_error( loginfo.log_error_fdes, subsystem, fmt, ap_file ); 
+			rc = vslapd_log_error( loginfo.log_error_fdes, subsystem, fmt, ap_file, 1 ); 
 		} 
 		LOG_ERROR_UNLOCK_WRITE();
 	} else {
 		/* log the problem in the stderr */
-    	rc = vslapd_log_error( NULL, subsystem, fmt, ap_err ); 
+    	rc = vslapd_log_error( NULL, subsystem, fmt, ap_err, 0 ); 
 	}
 	return( rc );
 }
@@ -1785,17 +1796,19 @@
     LOGFD	fp,
     char	*subsystem,	/* omitted if NULL */
     char	*fmt,
-    va_list	ap )
+    va_list	ap,
+	int     locked )
 {
-    time_t	tnl;
-    long	tz;
-    struct tm	*tmsp, tms;
-    char	tbuf[ TBUFSIZE ];
-    char	sign;
-    char	buffer[SLAPI_LOG_BUFSIZ];
-    int		blen;
-    char	*vbuf;
-	int header_len = 0;
+    time_t    tnl;
+    long      tz;
+    struct tm *tmsp, tms;
+    char      tbuf[ TBUFSIZE ];
+    char      sign;
+    char      buffer[SLAPI_LOG_BUFSIZ];
+    int       blen;
+    char      *vbuf;
+    int       header_len = 0;
+    int       err = 0;
 
     tnl = current_time();
 #ifdef _WIN32
@@ -1813,50 +1826,67 @@
 #else /* BSD_TIME */
     tz = - timezone;
     if ( tmsp->tm_isdst ) {
-	tz += 3600;
+    tz += 3600;
     }
 #endif /* BSD_TIME */
     sign = ( tz >= 0 ? '+' : '-' );
     if ( tz < 0 ) {
-	tz = -tz;
+    tz = -tz;
     }
     (void)strftime( tbuf, (size_t)TBUFSIZE, "%d/%b/%Y:%H:%M:%S", tmsp);
     sprintf( buffer, "[%s %c%02d%02d]%s%s - ", tbuf, sign, 
-					(int)( tz / 3600 ), (int)( tz % 3600 ),
-					subsystem ? " " : "",
-					subsystem ? subsystem : "");
-
-	/* Bug 561525: to be able to remove timestamp to not over pollute syslog, we may need
-		to skip the timestamp part of the message. 
-	  The size of the header is: 
-		the size of the time string
-		+ size of space 
-		+ size of one char (sign)
-		+ size of 2 char 
-		+ size of 2 char 
-		+ size of [ 
-		+ size of ]
-	*/
+                    (int)( tz / 3600 ), (int)( tz % 3600 ),
+                    subsystem ? " " : "",
+                    subsystem ? subsystem : "");
+
+    /* Bug 561525: to be able to remove timestamp to not over pollute syslog, we may need
+        to skip the timestamp part of the message. 
+      The size of the header is: 
+        the size of the time string
+        + size of space 
+        + size of one char (sign)
+        + size of 2 char 
+        + size of 2 char 
+        + size of [ 
+        + size of ]
+    */
 
-	header_len = strlen(tbuf) + 8;
+    header_len = strlen(tbuf) + 8;
 
     if ((vbuf = PR_vsmprintf(fmt, ap)) == NULL) {
-		return -1;
+        return -1;
     }
     blen = strlen(buffer);
-    if ((unsigned int)(SLAPI_LOG_BUFSIZ - blen ) < strlen(vbuf)) {
-		free (vbuf);
-		return -1;
-    }
-  
-    sprintf (buffer+blen, "%s", vbuf);
+    PR_snprintf (buffer+blen, sizeof(buffer)-blen, "%s", vbuf);
+    buffer[sizeof(buffer)-1] = '\0';
 
     if (fp)
-	LOG_WRITE_NOW(fp, buffer, strlen(buffer), header_len);
-
-
+#if 0
+        LOG_WRITE_NOW(fp, buffer, strlen(buffer), header_len, err);
+#else
+ do {
+	int size = strlen(buffer);
+	(err) = 0;
+	if ( slapi_write_buffer((fp), (buffer), (size)) != (size) ) 
+	{ 
+		PRErrorCode prerr = PR_GetError(); 
+		syslog(LOG_ERR, "Failed to write log, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s): %s\n", prerr, slapd_pr_strerror(prerr), (buffer)+(header_len) ); 
+		(err) = prerr; 
+	} 
+	/* Should be a flush in here ?? Yes because PR_SYNC doesn't work ! */ 
+	PR_Sync(fp); 
+	} while (0);
+#endif
     else  /* stderr is always unbuffered */
-	fprintf(stderr, "%s", buffer);
+        fprintf(stderr, "%s", buffer);
+
+    if (err) {
+        PR_snprintf(buffer, sizeof(buffer),
+                    "Writing to the errors log failed.  Exiting...");
+        log__error_emergency(buffer, 1, locked);
+        /* failed to write to the errors log.  should not continue. */
+        g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
+    }
 
     PR_smprintf_free (vbuf);
     return( 0 );
@@ -1865,31 +1895,31 @@
 int
 slapi_log_error( int severity, char *subsystem, char *fmt, ... )
 {
-    va_list	ap1;
-    va_list	ap2;
-    int		rc;
+    va_list ap1;
+    va_list ap2;
+    int     rc;
 
     if ( severity < SLAPI_LOG_MIN || severity > SLAPI_LOG_MAX ) {
-	(void)slapd_log_error_proc( subsystem,
-		"slapi_log_error: invalid severity %d (message %s)\n",
-		severity, fmt );
-	return( -1 );
+        (void)slapd_log_error_proc( subsystem,
+                "slapi_log_error: invalid severity %d (message %s)\n",
+                severity, fmt );
+        return( -1 );
     }
 
-
+    if (
 #ifdef _WIN32
-    if ( *module_ldap_debug
+         *module_ldap_debug
 #else
-    if ( slapd_ldap_debug
+         slapd_ldap_debug
 #endif
-	    & slapi_log_map[ severity ] ) {
-	va_start( ap1, fmt );
-	va_start( ap2, fmt );
-	rc = slapd_log_error_proc_internal( subsystem, fmt, ap1, ap2 );
-    	va_end( ap1 );
-    	va_end( ap2 );
+            & slapi_log_map[ severity ] ) {
+        va_start( ap1, fmt );
+        va_start( ap2, fmt );
+        rc = slapd_log_error_proc_internal( subsystem, fmt, ap1, ap2 );
+            va_end( ap1 );
+            va_end( ap2 );
     } else {
-	rc = 0;	/* nothing to be logged --> always return success */
+        rc = 0;        /* nothing to be logged --> always return success */
     }
 
     return( rc );
@@ -1899,13 +1929,13 @@
 slapi_is_loglevel_set ( const int loglevel )
 {
 
-	return ( 
+    return ( 
 #ifdef _WIN32
     *module_ldap_debug
 #else
     slapd_ldap_debug
 #endif
-	    & slapi_log_map[ loglevel ] ? 1 : 0);
+        & slapi_log_map[ loglevel ] ? 1 : 0);
 }
 
 
@@ -3474,6 +3504,31 @@
 	return logfile_type;
 }
 
+static void
+log__error_emergency(const char *errstr, int reopen, int locked)
+{
+	syslog(LOG_ERR, "%s\n", errstr);
+
+	/* emergency open */
+	if (!reopen) {
+		return;
+	}
+	if (NULL != loginfo.log_error_fdes) {
+		LOG_CLOSE(loginfo.log_error_fdes);
+	}
+	if (! LOG_OPEN_APPEND(loginfo.log_error_fdes, 
+						  loginfo.log_error_file, loginfo.log_error_mode)) {
+		PRErrorCode prerr = PR_GetError();
+		syslog(LOG_ERR, "Failed to reopen errors log file, " SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n", prerr, slapd_pr_strerror(prerr));
+	} else {
+		/* LDAPDebug locks ERROR_LOCK_WRITE internally */
+		if (locked) LOG_ERROR_UNLOCK_WRITE();
+		LDAPDebug(LDAP_DEBUG_ANY, "%s\n", errstr, 0, 0);
+		if (locked) LOG_ERROR_LOCK_WRITE( );
+	}
+	return;
+}
+
 /******************************************************************************
 * log__open_errorlogfile
 *
@@ -3485,7 +3540,7 @@
 {
 
 	time_t			now;
-	LOGFD			fp;
+	LOGFD			fp = NULL;
 	LOGFD			fpinfo = NULL;
 	char			tbuf[TBUFSIZE];
 	struct logfileinfo	*logp;
@@ -3500,6 +3555,9 @@
 		pw = slapdFrontendConfig->localuserinfo;
 	}
 	else {
+		PR_snprintf(buffer, sizeof(buffer),
+					"Invalid nsslapd-localuser. Cannot open the errors log. Exiting...");
+		log__error_emergency(buffer, 0, locked);
 		return LOG_UNABLE_TO_OPENFILE;
 	}
 #endif
@@ -3541,6 +3599,14 @@
 			log_convert_time (log->l_ctime, tbuf, 1/*short */);
 			PR_snprintf(newfile, sizeof(newfile), "%s.%s", loginfo.log_error_file, tbuf);
 			if (PR_Rename (loginfo.log_error_file, newfile) != PR_SUCCESS) {
+				PRErrorCode prerr = PR_GetError();
+				PR_snprintf(buffer, sizeof(buffer),
+					"Failed to rename errors log file, " 
+					SLAPI_COMPONENT_NAME_NSPR " error %d (%s). Exiting...", 
+					prerr, slapd_pr_strerror(prerr));
+				log__error_emergency(buffer, 1, 1);
+				slapi_ch_free((void **)&log);
+				if (!locked) LOG_ERROR_UNLOCK_WRITE();
 				return LOG_UNABLE_TO_OPENFILE;
 			}
 
@@ -3551,15 +3617,17 @@
 		}
 	} 
 
-
 	/* open a new log file */
 	if (! LOG_OPEN_APPEND(fp, loginfo.log_error_file, loginfo.log_error_mode)) {
-		LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
-				"errno %d (%s)\n",
+		PR_snprintf(buffer, sizeof(buffer),
+				"Failed to open errors log file %s: error %d (%s); Exiting...", 
 				loginfo.log_error_file, errno, slapd_system_strerror(errno));
+		log__error_emergency(buffer, 1, locked);
 		if (!locked) LOG_ERROR_UNLOCK_WRITE();
+		/* failed to write to the errors log.  should not continue. */
+		g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
 		/*if I have an old log file -- I should log a message
-		** that I can't open the  new file. Let the caller worry
+		** that I can't open the new file. Let the caller worry
 		** about logging message. 
 		*/
 		return LOG_UNABLE_TO_OPENFILE;
@@ -3583,9 +3651,10 @@
 	loginfo.log_error_state |= LOGGING_NEED_TITLE;
 
 	if (! LOG_OPEN_WRITE(fpinfo, loginfo.log_errorinfo_file, loginfo.log_error_mode)) {
-		LDAPDebug(LDAP_DEBUG_ANY, "WARNING: can't open file %s. "
-				"errno %d (%s)\n",
-				loginfo.log_errorinfo_file, errno, slapd_system_strerror(errno));
+		PR_snprintf(buffer, sizeof(buffer),
+				"Failed to open/write to errors log file %s: error %d (%s). Exiting...", 
+				loginfo.log_error_file, errno, slapd_system_strerror(errno));
+		log__error_emergency(buffer, 1, locked);
 		if (!locked) LOG_ERROR_UNLOCK_WRITE();
 		return LOG_UNABLE_TO_OPENFILE;
 	}
@@ -3597,7 +3666,7 @@
 	LOG_WRITE(fpinfo, buffer, strlen(buffer), 0);
 
 	logp = loginfo.log_error_logchain;
-	while ( logp) {
+	while (logp) {
 		log_convert_time (logp->l_ctime, tbuf, 1 /*short */);
 		PR_snprintf(buffer, sizeof(buffer), "LOGINFO:%s%s.%s (%lu) (%u)\n",
 			PREVLOGFILE, loginfo.log_error_file, tbuf, logp->l_ctime, logp->l_size);
@@ -3607,7 +3676,7 @@
 	/* Close the info file. We need only when we need to rotate to the
 	** next log file.
 	*/
-	if (fpinfo)  LOG_CLOSE(fpinfo);
+	if (fpinfo) LOG_CLOSE(fpinfo);
 
 	/* This is now the current error log */
 	loginfo.log_error_ctime = now;
@@ -3836,6 +3905,7 @@
 static void log_flush_buffer(LogBufferInfo *lbi, int type, int sync_now)
 {
 	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+	int err = 0;
 	
     if (type == SLAPD_ACCESS_LOG) {
 
@@ -3868,7 +3938,8 @@
 		if (!sync_now && slapdFrontendConfig->accesslogbuffering) {
 			LOG_WRITE(loginfo.log_access_fdes, lbi->top, lbi->current - lbi->top, 0);
 		} else {
-			LOG_WRITE_NOW(loginfo.log_access_fdes, lbi->top, lbi->current - lbi->top, 0);
+			LOG_WRITE_NOW(loginfo.log_access_fdes, lbi->top,
+								lbi->current - lbi->top, 0, err);
 		}
 
         lbi->current = lbi->top;


Index: libglobs.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/libglobs.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- libglobs.c	20 Sep 2007 16:54:38 -0000	1.21
+++ libglobs.c	5 Oct 2007 17:00:04 -0000	1.22
@@ -3034,22 +3034,26 @@
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
   if ( config_value_is_null( attrname, value, errorbuf, 1 )) {
-	return LDAP_OPERATIONS_ERROR;
+    return LDAP_OPERATIONS_ERROR;
   }
   
   retVal = log_update_errorlogdir ( value, apply );
   
   if ( retVal != LDAP_SUCCESS ) {
-	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			"Cannot open errorlog directory \"%s\", errors will "
-			"not be logged.", value );
+    PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
+      "Cannot open errorlog file \"%s\", errors cannot be logged.  Exiting...",
+      value );
+    syslog(LOG_ERR, 
+      "Cannot open errorlog file \"%s\", errors cannot be logged.  Exiting...",
+      value );
+    g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
   }
   
   if ( apply ) {
-	CFG_LOCK_WRITE(slapdFrontendConfig);
-	slapi_ch_free ( (void **) &(slapdFrontendConfig->errorlog) );
-	slapdFrontendConfig->errorlog = slapi_ch_strdup ( value );
-	CFG_UNLOCK_WRITE(slapdFrontendConfig);
+    CFG_LOCK_WRITE(slapdFrontendConfig);
+    slapi_ch_free ( (void **) &(slapdFrontendConfig->errorlog) );
+    slapdFrontendConfig->errorlog = slapi_ch_strdup ( value );
+    CFG_UNLOCK_WRITE(slapdFrontendConfig);
   }
   return retVal;
 }




More information about the Fedora-directory-commits mailing list