@@ -50,6 +50,8 @@ void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2, 3);
5050
5151static void elog_internal (int elevel , bool file_only , const char * fmt , va_list args )
5252 pg_attribute_printf (3 , 0 );
53+ static void elog_stderr (int elevel , const char * fmt , ...)
54+ pg_attribute_printf (2 , 3 );
5355
5456/* Functions to work with log files */
5557static void open_logfile (FILE * * file , const char * filename_format );
@@ -63,8 +65,8 @@ static FILE *log_file = NULL;
6365static FILE * error_log_file = NULL ;
6466
6567static bool exit_hook_registered = false;
66- /* Logging to file is in progress */
67- static bool logging_to_file = false;
68+ /* Logging of the current thread is in progress */
69+ static bool loggin_in_progress = false;
6870
6971static pthread_mutex_t log_file_mutex = PTHREAD_MUTEX_INITIALIZER ;
7072
@@ -111,11 +113,37 @@ write_elevel(FILE *stream, int elevel)
111113 fputs ("PANIC: " , stream );
112114 break ;
113115 default :
114- elog (ERROR , "invalid logging level: %d" , elevel );
116+ elog_stderr (ERROR , "invalid logging level: %d" , elevel );
115117 break ;
116118 }
117119}
118120
121+ /*
122+ * Exit with code if it is an error.
123+ * Check for in_cleanup flag to avoid deadlock in case of ERROR in cleanup
124+ * routines.
125+ */
126+ static void
127+ exit_if_necessary (int elevel )
128+ {
129+ if (elevel > WARNING && !in_cleanup )
130+ {
131+ /* Interrupt other possible routines */
132+ interrupted = true;
133+
134+ /* If this is not the main thread then don't call exit() */
135+ #ifdef WIN32
136+ if (main_tid != GetCurrentThreadId ())
137+ ExitThread (elevel );
138+ #else
139+ if (!pthread_equal (main_tid , pthread_self ()))
140+ pthread_exit (NULL );
141+ #endif
142+ else
143+ exit (elevel );
144+ }
145+ }
146+
119147/*
120148 * Logs to stderr or to log file and exit if ERROR or FATAL.
121149 *
@@ -132,18 +160,19 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
132160 time_t log_time = (time_t ) time (NULL );
133161 char strfbuf [128 ];
134162
135- write_to_file = !logging_to_file && elevel >= LOG_LEVEL_FILE &&
163+ write_to_file = elevel >= LOG_LEVEL_FILE && log_path [0 ] != '\0' ;
164+ write_to_error_log = elevel >= ERROR && error_log_filename &&
136165 log_path [0 ] != '\0' ;
137- write_to_error_log = !logging_to_file && elevel >= ERROR &&
138- error_log_filename && log_path [0 ] != '\0' ;
139166 write_to_stderr = elevel >= LOG_LEVEL_CONSOLE && !file_only ;
140167
141168 /*
142- * There is no need to lock if this is elog() from upper elog() and
143- * logging is not initialized.
169+ * There is no need to lock if this is elog() from upper elog().
144170 */
145- if (write_to_file || write_to_error_log || write_to_stderr )
171+ if (!loggin_in_progress )
172+ {
146173 pthread_mutex_lock (& log_file_mutex );
174+ loggin_in_progress = true;
175+ }
147176
148177 /* We need copy args only if we need write to error log file */
149178 if (write_to_error_log )
@@ -166,8 +195,6 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
166195 */
167196 if (write_to_file )
168197 {
169- logging_to_file = true;
170-
171198 if (log_file == NULL )
172199 {
173200 if (log_filename == NULL )
@@ -182,8 +209,6 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
182209 vfprintf (log_file , fmt , args );
183210 fputc ('\n' , log_file );
184211 fflush (log_file );
185-
186- logging_to_file = false;
187212 }
188213
189214 /*
@@ -193,8 +218,6 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
193218 */
194219 if (write_to_error_log )
195220 {
196- logging_to_file = true;
197-
198221 if (error_log_file == NULL )
199222 open_logfile (& error_log_file , error_log_filename );
200223
@@ -205,7 +228,6 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
205228 fputc ('\n' , error_log_file );
206229 fflush (error_log_file );
207230
208- logging_to_file = false;
209231 va_end (error_args );
210232 }
211233
@@ -228,25 +250,41 @@ elog_internal(int elevel, bool file_only, const char *fmt, va_list args)
228250 va_end (std_args );
229251 }
230252
231- if (write_to_file || write_to_error_log || write_to_stderr )
253+ if (loggin_in_progress )
254+ {
232255 pthread_mutex_unlock (& log_file_mutex );
256+ loggin_in_progress = false;
257+ }
258+
259+ exit_if_necessary (elevel );
260+ }
261+
262+ /*
263+ * Log only to stderr. It is called only within elog_internal() when another
264+ * logging already was started.
265+ */
266+ static void
267+ elog_stderr (int elevel , const char * fmt , ...)
268+ {
269+ va_list args ;
233270
234271 /*
235- * Exit with code if it is an error.
236- * Check for in_cleanup flag to avoid deadlock in case of ERROR in cleanup
237- * routines.
272+ * Do not log message if severity level is less than log_level.
273+ * It is the little optimisation to put it here not in elog_internal().
238274 */
239- if (elevel > WARNING && !in_cleanup )
240- {
241- /* Interrupt other possible routines */
242- interrupted = true;
275+ if (elevel < LOG_LEVEL_CONSOLE && elevel < ERROR )
276+ return ;
243277
244- /* If this is not the main thread then don't call exit() */
245- if (!pthread_equal (main_tid , pthread_self ()))
246- pthread_exit (NULL );
247- else
248- exit (elevel );
249- }
278+ va_start (args , fmt );
279+
280+ write_elevel (stderr , elevel );
281+ vfprintf (stderr , fmt , args );
282+ fputc ('\n' , stderr );
283+ fflush (stderr );
284+
285+ va_end (args );
286+
287+ exit_if_necessary (elevel );
250288}
251289
252290/*
@@ -417,7 +455,7 @@ logfile_getname(const char *format, time_t timestamp)
417455 struct tm * tm = localtime (& timestamp );
418456
419457 if (log_path [0 ] == '\0' )
420- elog (ERROR , "logging path is not set" );
458+ elog_stderr (ERROR , "logging path is not set" );
421459
422460 filename = (char * ) palloc (MAXPGPATH );
423461
@@ -427,7 +465,7 @@ logfile_getname(const char *format, time_t timestamp)
427465
428466 /* Treat log_filename as a strftime pattern */
429467 if (strftime (filename + len , MAXPGPATH - len , format , tm ) <= 0 )
430- elog (ERROR , "strftime(%s) failed: %s" , format , strerror (errno ));
468+ elog_stderr (ERROR , "strftime(%s) failed: %s" , format , strerror (errno ));
431469
432470 return filename ;
433471}
@@ -453,8 +491,8 @@ logfile_open(const char *filename, const char *mode)
453491 {
454492 int save_errno = errno ;
455493
456- elog (FATAL , "could not open log file \"%s\": %s" ,
457- filename , strerror (errno ));
494+ elog_stderr (FATAL , "could not open log file \"%s\": %s" ,
495+ filename , strerror (errno ));
458496 errno = save_errno ;
459497 }
460498
@@ -488,8 +526,8 @@ open_logfile(FILE **file, const char *filename_format)
488526 goto logfile_open ;
489527 }
490528 else
491- elog (ERROR , "cannot stat log file \"%s\": %s" ,
492- filename , strerror (errno ));
529+ elog_stderr (ERROR , "cannot stat log file \"%s\": %s" ,
530+ filename , strerror (errno ));
493531 }
494532 /* Found log file "filename" */
495533 logfile_exists = true;
@@ -505,35 +543,35 @@ open_logfile(FILE **file, const char *filename_format)
505543 if (stat (control , & control_st ) == -1 )
506544 {
507545 if (errno != ENOENT )
508- elog (ERROR , "cannot stat rotation file \"%s\": %s" ,
509- control , strerror (errno ));
546+ elog_stderr (ERROR , "cannot stat rotation file \"%s\": %s" ,
547+ control , strerror (errno ));
510548 }
511549 else
512550 {
513551 char buf [1024 ];
514552
515553 control_file = fopen (control , "r" );
516554 if (control_file == NULL )
517- elog (ERROR , "cannot open rotation file \"%s\": %s" ,
518- control , strerror (errno ));
555+ elog_stderr (ERROR , "cannot open rotation file \"%s\": %s" ,
556+ control , strerror (errno ));
519557
520558 if (fgets (buf , lengthof (buf ), control_file ))
521559 {
522560 time_t creation_time ;
523561
524562 if (!parse_int64 (buf , (int64 * ) & creation_time , 0 ))
525- elog (ERROR , "rotation file \"%s\" has wrong "
526- "creation timestamp \"%s\"" ,
527- control , buf );
563+ elog_stderr (ERROR , "rotation file \"%s\" has wrong "
564+ "creation timestamp \"%s\"" ,
565+ control , buf );
528566 /* Parsed creation time */
529567
530568 rotation_requested = (cur_time - creation_time ) >
531569 /* convert to seconds */
532570 log_rotation_age * 60 ;
533571 }
534572 else
535- elog (ERROR , "cannot read creation timestamp from "
536- "rotation file \"%s\"" , control );
573+ elog_stderr (ERROR , "cannot read creation timestamp from "
574+ "rotation file \"%s\"" , control );
537575
538576 fclose (control_file );
539577 }
@@ -560,8 +598,8 @@ open_logfile(FILE **file, const char *filename_format)
560598
561599 control_file = fopen (control , "w" );
562600 if (control_file == NULL )
563- elog (ERROR , "cannot open rotation file \"%s\": %s" ,
564- control , strerror (errno ));
601+ elog_stderr (ERROR , "cannot open rotation file \"%s\": %s" ,
602+ control , strerror (errno ));
565603
566604 fprintf (control_file , "%ld" , timestamp );
567605
0 commit comments