From: Maria Matejka Date: Fri, 29 Nov 2024 11:05:40 +0000 (+0100) Subject: Merge commit 'fc2b4b26' into thread-merge-2.16 X-Git-Tag: v3.0.0~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffba45657e503e2e279f111bdf52786e95236f0c;p=thirdparty%2Fbird.git Merge commit 'fc2b4b26' into thread-merge-2.16 Actually, completely rewritten the original patch as in v3, the logging initialization is much more complex and requires allocation. This way, to bootstrap properly, the logger has a pre-defined log target to stderr. --- ffba45657e503e2e279f111bdf52786e95236f0c diff --cc sysdep/unix/log.c index 98642e9c3,613a6aa54..9d77211bf --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@@ -42,16 -42,23 +42,16 @@@ _Thread_local uint this_thread_id #include -static pthread_mutex_t log_mutex; -static inline void log_lock(void) { pthread_mutex_lock(&log_mutex); } -static inline void log_unlock(void) { pthread_mutex_unlock(&log_mutex); } +static DOMAIN(logging) log_domain; +#define log_lock() LOCK_DOMAIN(logging, log_domain); +#define log_unlock() UNLOCK_DOMAIN(logging, log_domain); -static pthread_t main_thread; -void main_thread_init(void) { main_thread = pthread_self(); } -static int main_thread_self(void) { return pthread_equal(pthread_self(), main_thread); } +static struct log_channel * _Atomic global_logs; -#else - -static inline void log_lock(void) { } -static inline void log_unlock(void) { } -void main_thread_init(void) { } -static int main_thread_self(void) { return 1; } - -#endif +/* Logging flags to validly prepare logging messages */ +static _Atomic uint logging_flags; - static _Atomic uint logging_mask; ++static _Atomic uint logging_mask = ~0U; #ifdef HAVE_SYSLOG_H #include @@@ -178,87 -202,61 +178,98 @@@ log_rotate(struct log_channel *lc * in log(), so it should be written like *L_INFO. */ void -log_commit(int class, buffer *buf) +log_commit(log_buffer *buf) { - struct log_config *l; + /* Store the last pointer */ + buf->pos[LBP__MAX] = buf->buf.pos; - if (buf->pos == buf->end) - strcpy(buf->end - 100, " ... "); + /* Append the too-long message if too long */ + if (buf->buf.pos == buf->buf.end) +#define TOO_LONG " ... " + memcpy(buf->buf.end - sizeof TOO_LONG, TOO_LONG, sizeof TOO_LONG); +#undef TOO_LONG - log_lock(); - WALK_LIST(l, *current_log_list) ++ struct log_channel *glogs = atomic_load_explicit(&global_logs, memory_order_acquire); ++ if (!glogs) ++ { ++ static struct log_channel initial_stderr_log = { ++ .rf = &rf_stderr, ++ .mask = ~0, ++ .prepare = BIT32_ALL(LBPP_TERMINAL, LBP_CLASS, LBP_MSG), ++ }; ++ ++ glogs = &initial_stderr_log; ++ } ++ + for ( - struct log_channel *l = atomic_load_explicit(&global_logs, memory_order_acquire); - l; ++ struct log_channel *l = glogs; l; + l = atomic_load_explicit(&l->next, memory_order_acquire) + ) { - if (!(l->mask & (1 << class))) + uint mask = atomic_load_explicit(&l->mask, memory_order_acquire); + if (!(mask & (1 << buf->class))) continue; - if (l->fh) + + struct rfile *rf = atomic_load_explicit(&l->rf, memory_order_acquire); + sock *sk = atomic_load_explicit(&l->udp_sk, memory_order_acquire); + + if (rf || sk) { - if (l->terminal_flag) - fputs("bird: ", l->fh); - else if (l->udp_flag) + /* Construct the iovec */ + static char terminal_prefix[] = "bird: ", + newline[] = "\n"; + STATIC_ASSERT(sizeof newline == 2); + + struct iovec iov[LBP__MAX+2]; + uint iov_count = 0; + if (BIT32_TEST(&l->prepare, LBPP_TERMINAL)) + iov[iov_count++] = (struct iovec) { + .iov_base = terminal_prefix, + .iov_len = sizeof terminal_prefix - 1, + }; + + for (uint p = 0; p < LBP__MAX; p++) + if (BIT32_TEST(&l->prepare, p)) { - int pri = LOG_DAEMON | syslog_priorities[class]; - char tbuf[TM_DATETIME_BUFFER_SIZE]; - const char *hostname = (config && config->hostname) ? config->hostname : ""; - const char *fmt = "%b %d %T.%6f"; - if (!tm_format_real_time(tbuf, sizeof(tbuf), fmt, current_real_time())) - strcpy(tbuf, ""); - - /* Legacy RFC 3164 format, but with us precision */ - fprintf(l->fh, "<%d>%s %s %s: ", pri, tbuf, hostname, bird_name); + off_t sz = buf->pos[p+1] - buf->pos[p]; + if (sz > 0) + iov[iov_count++] = (struct iovec) { + .iov_base = buf->pos[p], + .iov_len = sz, + }; } - else - { - byte tbuf[TM_DATETIME_BUFFER_SIZE]; - const char *fmt = config ? config->tf_log.fmt1 : "%F %T.%3f"; - if (!tm_format_real_time(tbuf, sizeof(tbuf), fmt, current_real_time())) - strcpy(tbuf, ""); - - if (l->limit) - { - off_t msg_len = strlen(tbuf) + strlen(class_names[class]) + - (buf->pos - buf->start) + 5; - if (l->pos < 0) - l->pos = log_size(l); + if (rf) + { + iov[iov_count++] = (struct iovec) { + .iov_base = newline, + .iov_len = sizeof newline - 1, + }; - if (l->pos + msg_len > l->limit) - if (log_rotate(l) < 0) - continue; + do { + if (rf_writev(rf, iov, iov_count)) + break; - l->pos += msg_len; + log_lock(); + rf = atomic_load_explicit(&l->rf, memory_order_acquire); + if (rf_writev(rf, iov, iov_count)) + { + log_unlock(); + break; } - fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]); - } - fputs(buf->start, l->fh); - fputc('\n', l->fh); - fflush(l->fh); + log_rotate(l); + log_unlock(); + + rf = atomic_load_explicit(&l->rf, memory_order_relaxed); + } while (!rf_writev(rf, iov, iov_count)); + } + else if (sk) + { + while ((writev(sk->fd, iov, iov_count) < 0) && (errno == EINTR)) + ; + /* FIXME: Silently ignoring write errors */ + } } #ifdef HAVE_SYSLOG_H else