From 4bf862e3689b034d4e44cf94c5e50fe7ae05aee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 21 Apr 2015 18:49:37 +0200 Subject: [PATCH] syslog_daemon: Converted to BServer. * Instead of letting the kernel search for the syslog port, the daemon now registers itself with the kernel (which even solves a TODO). * A port is created for the actual log messages from the launch_daemon, and used on start. * However, the SyslogTest does not yet work, due to the BMessage <-> KMessage communication problems. --- headers/private/kernel/debug.h | 7 +- headers/private/syslog_daemon/syslog_daemon.h | 4 +- headers/private/system/syscalls.h | 3 +- src/servers/syslog_daemon/Jamfile | 3 +- src/servers/syslog_daemon/SyslogDaemon.cpp | 26 ++-- src/servers/syslog_daemon/SyslogDaemon.h | 5 +- src/servers/syslog_daemon/syslog_output.cpp | 12 +- src/system/kernel/debug/debug.cpp | 141 +++++++++--------- src/system/libroot/posix/syslog.cpp | 30 +++- src/tests/system/libroot/posix/Jamfile | 10 +- src/tests/system/libroot/posix/SyslogTest.cpp | 19 +-- 11 files changed, 137 insertions(+), 123 deletions(-) diff --git a/headers/private/kernel/debug.h b/headers/private/kernel/debug.h index 5cca136b9b..45332e4dbd 100644 --- a/headers/private/kernel/debug.h +++ b/headers/private/kernel/debug.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de + * Copyright 2002-2015, Axel Dörfler, axeld@pinc-software.de * Distributed under the terms of the Haiku License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -221,8 +221,9 @@ extern bool debug_is_debugged_team(team_id teamID); extern struct arch_debug_registers* debug_get_debug_registers(int32 cpu); -extern status_t _user_kernel_debugger(const char *message); -extern void _user_debug_output(const char *userString); +extern status_t _user_kernel_debugger(const char *message); +extern void _user_register_syslog_daemon(port_id port); +extern void _user_debug_output(const char *userString); #ifdef __cplusplus } diff --git a/headers/private/syslog_daemon/syslog_daemon.h b/headers/private/syslog_daemon/syslog_daemon.h index 513f9b7609..9897eb4e16 100644 --- a/headers/private/syslog_daemon/syslog_daemon.h +++ b/headers/private/syslog_daemon/syslog_daemon.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2015, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef SYSLOG_DAEMON_H @@ -9,7 +9,7 @@ #include -#define SYSLOG_PORT_NAME "syslog_daemon" +#define B_SYSTEM_LOGGER_SIGNATURE "application/x-vnd.Haiku-SystemLogger" #define SYSLOG_MESSAGE '_Syl' #define SYSLOG_ADD_LISTENER 'aSyl' diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index ebfd106ae6..d89dff7d9e 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2011, Haiku, Inc. All rights reserved. + * Copyright 2004-2015, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _SYSTEM_SYSCALLS_H @@ -472,6 +472,7 @@ extern status_t _kern_get_port_message_info_etc(port_id port, // debug support functions extern status_t _kern_kernel_debugger(const char *message); +extern void _kern_register_syslog_daemon(port_id port); extern void _kern_debugger(const char *message); extern int _kern_disable_debugger(int state); diff --git a/src/servers/syslog_daemon/Jamfile b/src/servers/syslog_daemon/Jamfile index 1d37179954..db32952460 100644 --- a/src/servers/syslog_daemon/Jamfile +++ b/src/servers/syslog_daemon/Jamfile @@ -1,6 +1,7 @@ SubDir HAIKU_TOP src servers syslog_daemon ; -UsePrivateHeaders syslog_daemon ; +UsePrivateHeaders app syslog_daemon ; +UsePrivateSystemHeaders ; AddResources syslog_daemon : SyslogDaemon.rdef ; diff --git a/src/servers/syslog_daemon/SyslogDaemon.cpp b/src/servers/syslog_daemon/SyslogDaemon.cpp index 2ae8561c51..8bc9cba62f 100644 --- a/src/servers/syslog_daemon/SyslogDaemon.cpp +++ b/src/servers/syslog_daemon/SyslogDaemon.cpp @@ -16,6 +16,10 @@ #include #include +#include +#include +#include + #include "listener_output.h" #include "syslog_output.h" @@ -24,12 +28,9 @@ #define B_TRANSLATION_CONTEXT "SyslogDaemon" -const char* kSignature = "application/x-vnd.Haiku-SystemLogger"; - - SyslogDaemon::SyslogDaemon() : - BApplication(kSignature), + BApplication(B_SYSTEM_LOGGER_SIGNATURE), fHandlerLock("handler lock") { } @@ -38,10 +39,12 @@ SyslogDaemon::SyslogDaemon() void SyslogDaemon::ReadyToRun() { - fPort = create_port(256, SYSLOG_PORT_NAME); - fDaemon = spawn_thread(daemon_thread, "daemon", B_NORMAL_PRIORITY, this); + fPort = BLaunchRoster().GetPort("logger"); + fDaemon = spawn_thread(_DaemonThread, "daemon", B_NORMAL_PRIORITY, this); + + if (fPort >= 0 && fDaemon >= 0) { + _kern_register_syslog_daemon(fPort); - if (fPort >= B_OK && fDaemon >= B_OK) { init_syslog_output(this); init_listener_output(this); @@ -128,7 +131,7 @@ SyslogDaemon::AddHandler(handler_func function) void -SyslogDaemon::Daemon() +SyslogDaemon::_Daemon() { char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1]; syslog_message& message = *(syslog_message*)buffer; @@ -168,13 +171,16 @@ SyslogDaemon::Daemon() int32 -SyslogDaemon::daemon_thread(void* data) +SyslogDaemon::_DaemonThread(void* data) { - ((SyslogDaemon*)data)->Daemon(); + ((SyslogDaemon*)data)->_Daemon(); return B_OK; } +// #pragma mark - + + int main(int argc, char** argv) { diff --git a/src/servers/syslog_daemon/SyslogDaemon.h b/src/servers/syslog_daemon/SyslogDaemon.h index 10986bf8b1..b544762fb9 100644 --- a/src/servers/syslog_daemon/SyslogDaemon.h +++ b/src/servers/syslog_daemon/SyslogDaemon.h @@ -28,8 +28,9 @@ public: void AddHandler(handler_func function); - void Daemon(); - static int32 daemon_thread(void* data); +private: + void _Daemon(); + static int32 _DaemonThread(void* data); private: thread_id fDaemon; diff --git a/src/servers/syslog_daemon/syslog_output.cpp b/src/servers/syslog_daemon/syslog_output.cpp index 457449c03c..0678ee2993 100644 --- a/src/servers/syslog_daemon/syslog_output.cpp +++ b/src/servers/syslog_daemon/syslog_output.cpp @@ -6,16 +6,16 @@ #include "syslog_output.h" -#include -#include -#include - -#include #include #include #include -#include #include +#include +#include + +#include +#include +#include static const char *kFacilities[] = { diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 7e9266dd39..1672d78303 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1,6 +1,6 @@ /* * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2015, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -98,6 +98,8 @@ static spinlock sSpinlock = B_SPINLOCK_INITIALIZER; static int32 sDebuggerOnCPU = -1; static sem_id sSyslogNotify = -1; +static thread_id sSyslogWriter = -1; +static port_id sSyslogPort = -1; static struct syslog_message* sSyslogMessage; static struct ring_buffer* sSyslogBuffer; static size_t sSyslogBufferOffset = 0; @@ -1188,8 +1190,6 @@ cmd_switch_cpu(int argc, char** argv) static status_t syslog_sender(void* data) { - status_t error = B_BAD_PORT_ID; - port_id port = -1; bool bufferPending = false; int32 length = 0; @@ -1208,69 +1208,56 @@ syslog_sender(void* data) sSyslogMessage->when = real_time_clock(); - if (error == B_BAD_PORT_ID) { - // last message couldn't be sent, try to locate the syslog_daemon - port = find_port(SYSLOG_PORT_NAME); - if (port < 0) { - // Don't recheck too quickly, since find_port) is rather - // expensive. - // TODO: Maybe using the port notification mechanism would be - // the better option here. Alternatively, and probably even - // better, the syslog daemon could register itself via a syscall - // (like the messaging service). We could even wait with - // starting this thread before that happened (end exit as soon - // as the port is gone). - snooze(1000000); - continue; + if (!bufferPending) { + // We need to have exclusive access to our syslog buffer + cpu_status state = disable_interrupts(); + acquire_spinlock(&sSpinlock); + + length = ring_buffer_readable(sSyslogBuffer) + - sSyslogBufferOffset; + if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) + length = SYSLOG_MAX_MESSAGE_LENGTH; + + length = ring_buffer_peek(sSyslogBuffer, sSyslogBufferOffset, + (uint8*)sSyslogMessage->message, length); + sSyslogBufferOffset += length; + if (sSyslogDropped) { + // Add drop marker - since parts had to be dropped, it's + // guaranteed that we have enough space in the buffer now. + ring_buffer_write(sSyslogBuffer, (uint8*)"", 6); + sSyslogDropped = false; } + + release_spinlock(&sSpinlock); + restore_interrupts(state); } - if (port >= B_OK) { - if (!bufferPending) { - // we need to have exclusive access to our syslog buffer - cpu_status state = disable_interrupts(); - acquire_spinlock(&sSpinlock); + if (length == 0) { + // The buffer we came here for might have been sent already + bufferPending = false; + continue; + } - length = ring_buffer_readable(sSyslogBuffer) - - sSyslogBufferOffset; - if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) - length = SYSLOG_MAX_MESSAGE_LENGTH; + status_t status = write_port_etc(sSyslogPort, SYSLOG_MESSAGE, + sSyslogMessage, sizeof(struct syslog_message) + length, + B_RELATIVE_TIMEOUT, 0); + if (status == B_BAD_PORT_ID) { + // The port is gone, there is no need to run anymore + sSyslogWriter = -1; + return status; + } - length = ring_buffer_peek(sSyslogBuffer, sSyslogBufferOffset, - (uint8*)sSyslogMessage->message, length); - sSyslogBufferOffset += length; - if (sSyslogDropped) { - // Add drop marker - since parts had to be dropped, it's - // guaranteed that we have enough space in the buffer now. - ring_buffer_write(sSyslogBuffer, (uint8*)"", 6); - sSyslogDropped = false; - } + if (status != B_OK) { + // Sending has failed - just wait, maybe it'll work later. + bufferPending = true; + continue; + } - release_spinlock(&sSpinlock); - restore_interrupts(state); - } - - if (length == 0) { - // the buffer we came here for might have been sent already - bufferPending = false; - continue; - } - - error = write_port_etc(port, SYSLOG_MESSAGE, sSyslogMessage, - sizeof(struct syslog_message) + length, B_RELATIVE_TIMEOUT, 0); - - if (error < B_OK) { - // sending has failed - just wait, maybe it'll work later. - bufferPending = true; - continue; - } - - if (bufferPending) { - // we could write the last pending buffer, try to read more - // from the syslog ring buffer - release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); - bufferPending = false; - } + if (bufferPending) { + // We could write the last pending buffer, try to read more + // from the syslog ring buffer + release_sem_etc(sSyslogNotify, 1, B_DO_NOT_RESCHEDULE); + bufferPending = false; } } @@ -1318,12 +1305,8 @@ syslog_init_post_threads(void) return B_OK; sSyslogNotify = create_sem(0, "syslog data"); - if (sSyslogNotify >= B_OK) { - thread_id thread = spawn_kernel_thread(syslog_sender, "syslog sender", - B_LOW_PRIORITY, NULL); - if (thread >= B_OK && resume_thread(thread) == B_OK) - return B_OK; - } + if (sSyslogNotify >= 0) + return B_OK; // initializing kernel syslog service failed -- disable it @@ -2275,18 +2258,17 @@ debug_is_debugged_team(team_id teamID) status_t -_user_kernel_debugger(const char *userMessage) +_user_kernel_debugger(const char* userMessage) { if (geteuid() != 0) return B_NOT_ALLOWED; char message[512]; strcpy(message, "USER: "); - size_t len = strlen(message); + size_t length = strlen(message); - if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) - || user_strlcpy(message + len, userMessage, sizeof(message) - len) - < 0) { + if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) || user_strlcpy( + message + length, userMessage, sizeof(message) - length) < 0) { return B_BAD_ADDRESS; } @@ -2295,6 +2277,23 @@ _user_kernel_debugger(const char *userMessage) } +void +_user_register_syslog_daemon(port_id port) +{ + if (geteuid() != 0 || !sSyslogOutputEnabled || sSyslogNotify < 0) + return; + + sSyslogPort = port; + + if (sSyslogWriter < 0) { + sSyslogWriter = spawn_kernel_thread(syslog_sender, "syslog sender", + B_LOW_PRIORITY, NULL); + if (sSyslogWriter >= 0) + resume_thread(sSyslogWriter); + } +} + + void _user_debug_output(const char* userString) { diff --git a/src/system/libroot/posix/syslog.cpp b/src/system/libroot/posix/syslog.cpp index 97d5b3c08f..71482c6f31 100644 --- a/src/system/libroot/posix/syslog.cpp +++ b/src/system/libroot/posix/syslog.cpp @@ -1,18 +1,21 @@ /* - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2015, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ -#include -#include - #include + #include #include #include #include +#include +#include +#include +#include + struct syslog_context { char ident[B_OS_NAME_LENGTH]; @@ -28,6 +31,7 @@ static syslog_context sTeamContext = { LOG_CONS }; static int32 sThreadContextSlot = -1; +static port_id sSystemLoggerPort = -1; static syslog_context * @@ -102,6 +106,22 @@ message_to_console(syslog_context *context, const char *text, va_list args) } +/*! Retrieves the port of the system logger from the launch_daemon. +*/ +static port_id +get_system_logger_port() +{ + if (sSystemLoggerPort >= 0) + return sSystemLoggerPort; + + BPrivate::KMessage data; + if (BPrivate::get_launch_data(B_SYSTEM_LOGGER_SIGNATURE, data) == B_OK) + sSystemLoggerPort = data.GetInt32("logger_port", -1); + + return sSystemLoggerPort; +} + + /*! Creates the message from the given context and sends it to the syslog daemon, if the priority mask matches. If the message couldn't be delivered, and LOG_CONS was set, it will @@ -117,7 +137,7 @@ send_syslog_message(syslog_context *context, int priority, const char *text, if ((context->mask & LOG_MASK(SYSLOG_PRIORITY(priority))) == 0) return; - port_id port = find_port(SYSLOG_PORT_NAME); + port_id port = get_system_logger_port(); if ((options & LOG_PERROR) != 0 || ((options & LOG_CONS) != 0 && port < B_OK)) { // if asked for, print out the (simplified) message on stderr diff --git a/src/tests/system/libroot/posix/Jamfile b/src/tests/system/libroot/posix/Jamfile index f93588e80d..92b09df7b2 100644 --- a/src/tests/system/libroot/posix/Jamfile +++ b/src/tests/system/libroot/posix/Jamfile @@ -1,15 +1,12 @@ SubDir HAIKU_TOP src tests system libroot posix ; -UsePrivateHeaders libroot syslog_daemon ; - - # filter warnings about strftime()-formats in locale_test TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH) on [ FGristFiles locale_test.o ] += -Wno-format ; # POSIX/libc tests SimpleTest abort_test : abort_test.cpp ; -SimpleTest SyslogTest : SyslogTest.cpp syslog.cpp ; +SimpleTest SyslogTest : SyslogTest.cpp ; SimpleTest clearenv : clearenv.cpp ; SimpleTest dirent_test : dirent_test.cpp ; SimpleTest flock_test : flock_test.cpp ; @@ -72,10 +69,5 @@ SimpleTest test_wctype : test_wctype.c ; SimpleTest wcs_test : wcs_test.cpp ; -# Tell Jam where to find these sources -SEARCH on [ FGristFiles - syslog.cpp - ] = [ FDirName $(HAIKU_TOP) src system libroot posix ] ; - SubInclude HAIKU_TOP src tests system libroot posix math ; SubInclude HAIKU_TOP src tests system libroot posix string ; diff --git a/src/tests/system/libroot/posix/SyslogTest.cpp b/src/tests/system/libroot/posix/SyslogTest.cpp index 616126eda0..6c74c7bdb8 100644 --- a/src/tests/system/libroot/posix/SyslogTest.cpp +++ b/src/tests/system/libroot/posix/SyslogTest.cpp @@ -1,27 +1,20 @@ -/* -** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ +/* + * Copyright 2003-2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ -#include -#include - #include #include #include #include -int +int main(int argc, char **argv) { - port_id port = find_port(SYSLOG_PORT_NAME); - if (port < B_OK) - fprintf(stderr, "The (new) syslog_daemon should be running!\n"); - openlog_team("SyslogTest", LOG_PID, LOG_USER); - + log_team(LOG_ERR, "this is %.", "a test"); int mask = setlogmask_team(LOG_MASK(LOG_CRIT));