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.
This commit is contained in:
Axel Dörfler
2015-07-22 20:40:47 +02:00
parent 9d69dc097d
commit 4bf862e368
11 changed files with 137 additions and 123 deletions
+4 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2010, Axel Dörfler, [email protected] * Copyright 2002-2015, Axel Dörfler, [email protected]
* Distributed under the terms of the Haiku License. * Distributed under the terms of the Haiku License.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * 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 struct arch_debug_registers* debug_get_debug_registers(int32 cpu);
extern status_t _user_kernel_debugger(const char *message); extern status_t _user_kernel_debugger(const char *message);
extern void _user_debug_output(const char *userString); extern void _user_register_syslog_daemon(port_id port);
extern void _user_debug_output(const char *userString);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2003-2015, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef SYSLOG_DAEMON_H #ifndef SYSLOG_DAEMON_H
@@ -9,7 +9,7 @@
#include <OS.h> #include <OS.h>
#define SYSLOG_PORT_NAME "syslog_daemon" #define B_SYSTEM_LOGGER_SIGNATURE "application/x-vnd.Haiku-SystemLogger"
#define SYSLOG_MESSAGE '_Syl' #define SYSLOG_MESSAGE '_Syl'
#define SYSLOG_ADD_LISTENER 'aSyl' #define SYSLOG_ADD_LISTENER 'aSyl'
+2 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _SYSTEM_SYSCALLS_H #ifndef _SYSTEM_SYSCALLS_H
@@ -472,6 +472,7 @@ extern status_t _kern_get_port_message_info_etc(port_id port,
// debug support functions // debug support functions
extern status_t _kern_kernel_debugger(const char *message); 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 void _kern_debugger(const char *message);
extern int _kern_disable_debugger(int state); extern int _kern_disable_debugger(int state);
+2 -1
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src servers syslog_daemon ; SubDir HAIKU_TOP src servers syslog_daemon ;
UsePrivateHeaders syslog_daemon ; UsePrivateHeaders app syslog_daemon ;
UsePrivateSystemHeaders ;
AddResources syslog_daemon : SyslogDaemon.rdef ; AddResources syslog_daemon : SyslogDaemon.rdef ;
+16 -10
View File
@@ -16,6 +16,10 @@
#include <Path.h> #include <Path.h>
#include <TextView.h> #include <TextView.h>
#include <LaunchRoster.h>
#include <syscalls.h>
#include <syslog_daemon.h>
#include "listener_output.h" #include "listener_output.h"
#include "syslog_output.h" #include "syslog_output.h"
@@ -24,12 +28,9 @@
#define B_TRANSLATION_CONTEXT "SyslogDaemon" #define B_TRANSLATION_CONTEXT "SyslogDaemon"
const char* kSignature = "application/x-vnd.Haiku-SystemLogger";
SyslogDaemon::SyslogDaemon() SyslogDaemon::SyslogDaemon()
: :
BApplication(kSignature), BApplication(B_SYSTEM_LOGGER_SIGNATURE),
fHandlerLock("handler lock") fHandlerLock("handler lock")
{ {
} }
@@ -38,10 +39,12 @@ SyslogDaemon::SyslogDaemon()
void void
SyslogDaemon::ReadyToRun() SyslogDaemon::ReadyToRun()
{ {
fPort = create_port(256, SYSLOG_PORT_NAME); fPort = BLaunchRoster().GetPort("logger");
fDaemon = spawn_thread(daemon_thread, "daemon", B_NORMAL_PRIORITY, this); 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_syslog_output(this);
init_listener_output(this); init_listener_output(this);
@@ -128,7 +131,7 @@ SyslogDaemon::AddHandler(handler_func function)
void void
SyslogDaemon::Daemon() SyslogDaemon::_Daemon()
{ {
char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1]; char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1];
syslog_message& message = *(syslog_message*)buffer; syslog_message& message = *(syslog_message*)buffer;
@@ -168,13 +171,16 @@ SyslogDaemon::Daemon()
int32 int32
SyslogDaemon::daemon_thread(void* data) SyslogDaemon::_DaemonThread(void* data)
{ {
((SyslogDaemon*)data)->Daemon(); ((SyslogDaemon*)data)->_Daemon();
return B_OK; return B_OK;
} }
// #pragma mark -
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
+3 -2
View File
@@ -28,8 +28,9 @@ public:
void AddHandler(handler_func function); void AddHandler(handler_func function);
void Daemon(); private:
static int32 daemon_thread(void* data); void _Daemon();
static int32 _DaemonThread(void* data);
private: private:
thread_id fDaemon; thread_id fDaemon;
+6 -6
View File
@@ -6,16 +6,16 @@
#include "syslog_output.h" #include "syslog_output.h"
#include <FindDirectory.h>
#include <Path.h>
#include <driver_settings.h>
#include <syslog.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
#include <FindDirectory.h>
#include <Path.h>
#include <driver_settings.h>
static const char *kFacilities[] = { static const char *kFacilities[] = {
+70 -71
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008-2011, Ingo Weinhold, [email protected]. * Copyright 2008-2011, Ingo Weinhold, [email protected].
* Copyright 2002-2010, Axel Dörfler, [email protected]. * Copyright 2002-2015, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001, Travis Geiselbrecht. All rights reserved. * Copyright 2001, Travis Geiselbrecht. All rights reserved.
@@ -98,6 +98,8 @@ static spinlock sSpinlock = B_SPINLOCK_INITIALIZER;
static int32 sDebuggerOnCPU = -1; static int32 sDebuggerOnCPU = -1;
static sem_id sSyslogNotify = -1; static sem_id sSyslogNotify = -1;
static thread_id sSyslogWriter = -1;
static port_id sSyslogPort = -1;
static struct syslog_message* sSyslogMessage; static struct syslog_message* sSyslogMessage;
static struct ring_buffer* sSyslogBuffer; static struct ring_buffer* sSyslogBuffer;
static size_t sSyslogBufferOffset = 0; static size_t sSyslogBufferOffset = 0;
@@ -1188,8 +1190,6 @@ cmd_switch_cpu(int argc, char** argv)
static status_t static status_t
syslog_sender(void* data) syslog_sender(void* data)
{ {
status_t error = B_BAD_PORT_ID;
port_id port = -1;
bool bufferPending = false; bool bufferPending = false;
int32 length = 0; int32 length = 0;
@@ -1208,69 +1208,56 @@ syslog_sender(void* data)
sSyslogMessage->when = real_time_clock(); sSyslogMessage->when = real_time_clock();
if (error == B_BAD_PORT_ID) { if (!bufferPending) {
// last message couldn't be sent, try to locate the syslog_daemon // We need to have exclusive access to our syslog buffer
port = find_port(SYSLOG_PORT_NAME); cpu_status state = disable_interrupts();
if (port < 0) { acquire_spinlock(&sSpinlock);
// Don't recheck too quickly, since find_port) is rather
// expensive. length = ring_buffer_readable(sSyslogBuffer)
// TODO: Maybe using the port notification mechanism would be - sSyslogBufferOffset;
// the better option here. Alternatively, and probably even if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH)
// better, the syslog daemon could register itself via a syscall length = SYSLOG_MAX_MESSAGE_LENGTH;
// (like the messaging service). We could even wait with
// starting this thread before that happened (end exit as soon length = ring_buffer_peek(sSyslogBuffer, sSyslogBufferOffset,
// as the port is gone). (uint8*)sSyslogMessage->message, length);
snooze(1000000); sSyslogBufferOffset += length;
continue; 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*)"<DROP>", 6);
sSyslogDropped = false;
} }
release_spinlock(&sSpinlock);
restore_interrupts(state);
} }
if (port >= B_OK) { if (length == 0) {
if (!bufferPending) { // The buffer we came here for might have been sent already
// we need to have exclusive access to our syslog buffer bufferPending = false;
cpu_status state = disable_interrupts(); continue;
acquire_spinlock(&sSpinlock); }
length = ring_buffer_readable(sSyslogBuffer) status_t status = write_port_etc(sSyslogPort, SYSLOG_MESSAGE,
- sSyslogBufferOffset; sSyslogMessage, sizeof(struct syslog_message) + length,
if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH) B_RELATIVE_TIMEOUT, 0);
length = SYSLOG_MAX_MESSAGE_LENGTH; 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, if (status != B_OK) {
(uint8*)sSyslogMessage->message, length); // Sending has failed - just wait, maybe it'll work later.
sSyslogBufferOffset += length; bufferPending = true;
if (sSyslogDropped) { continue;
// 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*)"<DROP>", 6);
sSyslogDropped = false;
}
release_spinlock(&sSpinlock); if (bufferPending) {
restore_interrupts(state); // 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);
if (length == 0) { bufferPending = false;
// 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;
}
} }
} }
@@ -1318,12 +1305,8 @@ syslog_init_post_threads(void)
return B_OK; return B_OK;
sSyslogNotify = create_sem(0, "syslog data"); sSyslogNotify = create_sem(0, "syslog data");
if (sSyslogNotify >= B_OK) { if (sSyslogNotify >= 0)
thread_id thread = spawn_kernel_thread(syslog_sender, "syslog sender", return B_OK;
B_LOW_PRIORITY, NULL);
if (thread >= B_OK && resume_thread(thread) == B_OK)
return B_OK;
}
// initializing kernel syslog service failed -- disable it // initializing kernel syslog service failed -- disable it
@@ -2275,18 +2258,17 @@ debug_is_debugged_team(team_id teamID)
status_t status_t
_user_kernel_debugger(const char *userMessage) _user_kernel_debugger(const char* userMessage)
{ {
if (geteuid() != 0) if (geteuid() != 0)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
char message[512]; char message[512];
strcpy(message, "USER: "); strcpy(message, "USER: ");
size_t len = strlen(message); size_t length = strlen(message);
if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) if (userMessage == NULL || !IS_USER_ADDRESS(userMessage) || user_strlcpy(
|| user_strlcpy(message + len, userMessage, sizeof(message) - len) message + length, userMessage, sizeof(message) - length) < 0) {
< 0) {
return B_BAD_ADDRESS; 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 void
_user_debug_output(const char* userString) _user_debug_output(const char* userString)
{ {
+25 -5
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#include <syslog_daemon.h>
#include <TLS.h>
#include <syslog.h> #include <syslog.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <launch.h>
#include <syslog_daemon.h>
#include <TLS.h>
#include <util/KMessage.h>
struct syslog_context { struct syslog_context {
char ident[B_OS_NAME_LENGTH]; char ident[B_OS_NAME_LENGTH];
@@ -28,6 +31,7 @@ static syslog_context sTeamContext = {
LOG_CONS LOG_CONS
}; };
static int32 sThreadContextSlot = -1; static int32 sThreadContextSlot = -1;
static port_id sSystemLoggerPort = -1;
static syslog_context * 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 /*! Creates the message from the given context and sends it to the syslog
daemon, if the priority mask matches. daemon, if the priority mask matches.
If the message couldn't be delivered, and LOG_CONS was set, it will 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) if ((context->mask & LOG_MASK(SYSLOG_PRIORITY(priority))) == 0)
return; return;
port_id port = find_port(SYSLOG_PORT_NAME); port_id port = get_system_logger_port();
if ((options & LOG_PERROR) != 0 if ((options & LOG_PERROR) != 0
|| ((options & LOG_CONS) != 0 && port < B_OK)) { || ((options & LOG_CONS) != 0 && port < B_OK)) {
// if asked for, print out the (simplified) message on stderr // if asked for, print out the (simplified) message on stderr
+1 -9
View File
@@ -1,15 +1,12 @@
SubDir HAIKU_TOP src tests system libroot posix ; SubDir HAIKU_TOP src tests system libroot posix ;
UsePrivateHeaders libroot syslog_daemon ;
# filter warnings about strftime()-formats in locale_test # filter warnings about strftime()-formats in locale_test
TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH) TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH)
on [ FGristFiles locale_test.o ] += -Wno-format ; on [ FGristFiles locale_test.o ] += -Wno-format ;
# POSIX/libc tests # POSIX/libc tests
SimpleTest abort_test : abort_test.cpp ; SimpleTest abort_test : abort_test.cpp ;
SimpleTest SyslogTest : SyslogTest.cpp syslog.cpp ; SimpleTest SyslogTest : SyslogTest.cpp ;
SimpleTest clearenv : clearenv.cpp ; SimpleTest clearenv : clearenv.cpp ;
SimpleTest dirent_test : dirent_test.cpp ; SimpleTest dirent_test : dirent_test.cpp ;
SimpleTest flock_test : flock_test.cpp ; SimpleTest flock_test : flock_test.cpp ;
@@ -72,10 +69,5 @@ SimpleTest test_wctype : test_wctype.c ;
SimpleTest wcs_test : wcs_test.cpp ; 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 math ;
SubInclude HAIKU_TOP src tests system libroot posix string ; SubInclude HAIKU_TOP src tests system libroot posix string ;
+3 -10
View File
@@ -1,12 +1,9 @@
/* /*
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2003-2015, Axel Dörfler, axeld@pinc-software.de.
** Distributed under the terms of the OpenBeOS License. * Distributed under the terms of the MIT License.
*/ */
#include <syslog_daemon.h>
#include <OS.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -16,10 +13,6 @@
int int
main(int argc, char **argv) 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); openlog_team("SyslogTest", LOG_PID, LOG_USER);
log_team(LOG_ERR, "this is %.", "a test"); log_team(LOG_ERR, "this is %.", "a test");