mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
log: Close log and err file descriptors before aborting
Part of 31594.
This commit is contained in:
parent
a22fbab986
commit
1609916c79
@ -172,7 +172,7 @@ crash_handler(int sig, siginfo_t *si, void *ctx_)
|
||||
for (i=0; i < n_fds; ++i)
|
||||
backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
|
||||
|
||||
abort();
|
||||
tor_raw_abort_();
|
||||
}
|
||||
|
||||
/** Write a backtrace to all of the emergency-error fds. */
|
||||
|
@ -208,6 +208,18 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
|
||||
dump_stack_symbols_to_error_fds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the abort() function to kill the current process with a fatal
|
||||
* error. But first, close the raw error file descriptors, so error messages
|
||||
* are written before process termination.
|
||||
**/
|
||||
void
|
||||
tor_raw_abort_(void)
|
||||
{
|
||||
tor_log_close_sigsafe_err_fds();
|
||||
abort();
|
||||
}
|
||||
|
||||
/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
|
||||
* in range 2..16 inclusive. */
|
||||
static int
|
||||
@ -242,7 +254,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len,
|
||||
unsigned digit = (unsigned) (x % radix);
|
||||
if (cp <= buf) {
|
||||
/* Not tor_assert(); see above. */
|
||||
abort();
|
||||
tor_raw_abort_();
|
||||
}
|
||||
--cp;
|
||||
*cp = "0123456789ABCDEF"[digit];
|
||||
@ -251,7 +263,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len,
|
||||
|
||||
/* NOT tor_assert; see above. */
|
||||
if (cp != buf) {
|
||||
abort(); // LCOV_EXCL_LINE
|
||||
tor_raw_abort_(); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return len;
|
||||
|
@ -20,13 +20,13 @@
|
||||
#define raw_assert(expr) STMT_BEGIN \
|
||||
if (!(expr)) { \
|
||||
tor_raw_assertion_failed_msg_(__FILE__, __LINE__, #expr, NULL); \
|
||||
abort(); \
|
||||
tor_raw_abort_(); \
|
||||
} \
|
||||
STMT_END
|
||||
#define raw_assert_unreached(expr) raw_assert(0)
|
||||
#define raw_assert_unreached_msg(msg) STMT_BEGIN \
|
||||
tor_raw_assertion_failed_msg_(__FILE__, __LINE__, "0", (msg)); \
|
||||
abort(); \
|
||||
tor_raw_abort_(); \
|
||||
STMT_END
|
||||
|
||||
void tor_raw_assertion_failed_msg_(const char *file, int line,
|
||||
@ -43,6 +43,8 @@ void tor_log_reset_sigsafe_err_fds(void);
|
||||
void tor_log_close_sigsafe_err_fds(void);
|
||||
void tor_log_sigsafe_err_set_granularity(int ms);
|
||||
|
||||
void tor_raw_abort_(void) ATTR_NORETURN;
|
||||
|
||||
int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
|
||||
int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
|
||||
|
||||
|
@ -224,6 +224,7 @@ int log_global_min_severity_ = LOG_NOTICE;
|
||||
|
||||
static void delete_log(logfile_t *victim);
|
||||
static void close_log(logfile_t *victim);
|
||||
static void close_log_sigsafe(logfile_t *victim);
|
||||
|
||||
static char *domain_to_string(log_domain_mask_t domain,
|
||||
char *buf, size_t buflen);
|
||||
@ -833,6 +834,30 @@ logs_free_all(void)
|
||||
* that happened between here and the end of execution. */
|
||||
}
|
||||
|
||||
/** Close signal-safe log files.
|
||||
* Closing the log files makes the process and OS flush log buffers.
|
||||
*
|
||||
* This function is safe to call from a signal handler. It should only be
|
||||
* called when shutting down the log or err modules. It is currenly called
|
||||
* by the err module, when terminating the process on an abnormal condition.
|
||||
*/
|
||||
void
|
||||
logs_close_sigsafe(void)
|
||||
{
|
||||
logfile_t *victim, *next;
|
||||
/* We can't LOCK_LOGS() in a signal handler, because it may call
|
||||
* signal-unsafe functions. And we can't deallocate memory, either. */
|
||||
next = logfiles;
|
||||
logfiles = NULL;
|
||||
while (next) {
|
||||
victim = next;
|
||||
next = next->next;
|
||||
if (victim->needs_close) {
|
||||
close_log_sigsafe(victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove and free the log entry <b>victim</b> from the linked-list
|
||||
* logfiles (it is probably present, but it might not be due to thread
|
||||
* racing issues). After this function is called, the caller shouldn't
|
||||
@ -858,14 +883,27 @@ delete_log(logfile_t *victim)
|
||||
log_free(victim);
|
||||
}
|
||||
|
||||
/** Helper: release system resources (but not memory) held by a single
|
||||
* signal-safe logfile_t. If the log's resources can not be released in
|
||||
* a signal handler, does nothing. */
|
||||
static void
|
||||
close_log_sigsafe(logfile_t *victim)
|
||||
{
|
||||
if (victim->needs_close && victim->fd >= 0) {
|
||||
/* We can't do anything useful here if close() fails: we're shutting
|
||||
* down logging, and the err module only does fatal errors. */
|
||||
close(victim->fd);
|
||||
victim->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper: release system resources (but not memory) held by a single
|
||||
* logfile_t. */
|
||||
static void
|
||||
close_log(logfile_t *victim)
|
||||
{
|
||||
if (victim->needs_close && victim->fd >= 0) {
|
||||
close(victim->fd);
|
||||
victim->fd = -1;
|
||||
if (victim->needs_close) {
|
||||
close_log_sigsafe(victim);
|
||||
} else if (victim->is_syslog) {
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
if (--syslog_count == 0) {
|
||||
|
@ -170,6 +170,7 @@ void logs_set_domain_logging(int enabled);
|
||||
int get_min_log_level(void);
|
||||
void switch_logs_debug(void);
|
||||
void logs_free_all(void);
|
||||
void logs_close_sigsafe(void);
|
||||
void add_temp_log(int min_severity);
|
||||
void close_temp_logs(void);
|
||||
void rollback_log_changes(void);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "lib/log/util_bug.h"
|
||||
#include "lib/log/log.h"
|
||||
#include "lib/err/backtrace.h"
|
||||
#include "lib/err/torerr.h"
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
#include "lib/smartlist_core/smartlist_core.h"
|
||||
#include "lib/smartlist_core/smartlist_foreach.h"
|
||||
@ -122,16 +123,18 @@ tor_bug_occurred_(const char *fname, unsigned int line,
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the abort() function to kill the current process with a fatal
|
||||
* error.
|
||||
* Call the tor_raw_abort_() function to close raw logs, then kill the current
|
||||
* process with a fatal error. But first, close the file-based log file
|
||||
* descriptors, so error messages are written before process termination.
|
||||
*
|
||||
* (This is a separate function so that we declare it in util_bug.h without
|
||||
* including stdlib in all the users of util_bug.h)
|
||||
* including torerr.h in all the users of util_bug.h)
|
||||
**/
|
||||
void
|
||||
tor_abort_(void)
|
||||
{
|
||||
abort();
|
||||
logs_close_sigsafe();
|
||||
tor_raw_abort_();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -14,5 +14,6 @@
|
||||
#define trunnel_reallocarray tor_reallocarray
|
||||
#define trunnel_assert tor_assert
|
||||
#define trunnel_memwipe(mem, len) memwipe((mem), 0, (len))
|
||||
#define trunnel_abort tor_abort_
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user