|
@@ -225,6 +225,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);
|
|
@@ -665,13 +666,24 @@ tor_log_update_sigsafe_err_fds(void)
|
|
|
const logfile_t *lf;
|
|
|
int found_real_stderr = 0;
|
|
|
|
|
|
- int fds[TOR_SIGSAFE_LOG_MAX_FDS];
|
|
|
+
|
|
|
+ * the log module, and err_fds are the fds used by the err module.
|
|
|
+ * For stdio logs, the log_fd and err_fd values are identical,
|
|
|
+ * and the err module closes the fd on shutdown.
|
|
|
+ * For file logs, the err_fd is a dup() of the log_fd,
|
|
|
+ * and the log and err modules both close their respective fds on shutdown.
|
|
|
+ * (Once all fds representing a file are closed, the underlying file is
|
|
|
+ * closed.)
|
|
|
+ */
|
|
|
+ int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
|
|
|
+ int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
|
|
|
int n_fds;
|
|
|
|
|
|
LOCK_LOGS();
|
|
|
|
|
|
- * we dup2 /dev/null to stderr, */
|
|
|
- fds[0] = STDERR_FILENO;
|
|
|
+ * we dup2 /dev/null to stderr.
|
|
|
+ * For stderr, log_fds and err_fds are the same. */
|
|
|
+ log_fds[0] = err_fds[0] = STDERR_FILENO;
|
|
|
n_fds = 1;
|
|
|
|
|
|
for (lf = logfiles; lf; lf = lf->next) {
|
|
@@ -685,25 +697,39 @@ tor_log_update_sigsafe_err_fds(void)
|
|
|
(LD_BUG|LD_GENERAL)) {
|
|
|
if (lf->fd == STDERR_FILENO)
|
|
|
found_real_stderr = 1;
|
|
|
-
|
|
|
- if (int_array_contains(fds, n_fds, lf->fd))
|
|
|
+
|
|
|
+ if (int_array_contains(log_fds, n_fds, lf->fd))
|
|
|
continue;
|
|
|
- fds[n_fds++] = lf->fd;
|
|
|
+
|
|
|
+ log_fds[n_fds] = lf->fd;
|
|
|
+ if (lf->needs_close) {
|
|
|
+
|
|
|
+ * module's fd, and tor_log_close_sigsafe_err_fds() closes the err
|
|
|
+ * module's fd. Both refer to the same file. */
|
|
|
+ err_fds[n_fds] = dup(lf->fd);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ * tor_log_close_sigsafe_err_fds() closes stdio logs. */
|
|
|
+ err_fds[n_fds] = lf->fd;
|
|
|
+ }
|
|
|
+ n_fds++;
|
|
|
if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!found_real_stderr &&
|
|
|
- int_array_contains(fds, n_fds, STDOUT_FILENO)) {
|
|
|
+ int_array_contains(log_fds, n_fds, STDOUT_FILENO)) {
|
|
|
|
|
|
raw_assert(n_fds >= 2);
|
|
|
- fds[0] = fds[--n_fds];
|
|
|
+ --n_fds;
|
|
|
+ log_fds[0] = log_fds[n_fds];
|
|
|
+ err_fds[0] = err_fds[n_fds];
|
|
|
}
|
|
|
|
|
|
UNLOCK_LOGS();
|
|
|
|
|
|
- tor_log_set_sigsafe_err_fds(fds, n_fds);
|
|
|
+ tor_log_set_sigsafe_err_fds(err_fds, n_fds);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -809,6 +835,30 @@ logs_free_all(void)
|
|
|
* that happened between here and the end of execution. */
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * 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;
|
|
|
+
|
|
|
+ * 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* logfiles (it is probably present, but it might not be due to thread
|
|
|
* racing issues). After this function is called, the caller shouldn't
|
|
@@ -835,13 +885,26 @@ delete_log(logfile_t *victim)
|
|
|
}
|
|
|
|
|
|
|
|
|
- * logfile_t. */
|
|
|
+ * signal-safe logfile_t. If the log's resources can not be released in
|
|
|
+ * a signal handler, does nothing. */
|
|
|
static void
|
|
|
-close_log(logfile_t *victim)
|
|
|
+close_log_sigsafe(logfile_t *victim)
|
|
|
{
|
|
|
if (victim->needs_close && victim->fd >= 0) {
|
|
|
+
|
|
|
+ * down logging, and the err module only does fatal errors. */
|
|
|
close(victim->fd);
|
|
|
victim->fd = -1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+ * logfile_t. */
|
|
|
+static void
|
|
|
+close_log(logfile_t *victim)
|
|
|
+{
|
|
|
+ if (victim->needs_close) {
|
|
|
+ close_log_sigsafe(victim);
|
|
|
} else if (victim->is_syslog) {
|
|
|
#ifdef HAVE_SYSLOG_H
|
|
|
if (--syslog_count == 0) {
|