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-04-21 18:49:37 +02:00
parent 9d69dc097d
commit 4bf862e368
11 changed files with 137 additions and 123 deletions

View File

@ -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
}

View File

@ -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 <OS.h>
#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'

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.
*/
#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);

View File

@ -1,6 +1,7 @@
SubDir HAIKU_TOP src servers syslog_daemon ;
UsePrivateHeaders syslog_daemon ;
UsePrivateHeaders app syslog_daemon ;
UsePrivateSystemHeaders ;
AddResources syslog_daemon : SyslogDaemon.rdef ;

View File

@ -16,6 +16,10 @@
#include <Path.h>
#include <TextView.h>
#include <LaunchRoster.h>
#include <syscalls.h>
#include <syslog_daemon.h>
#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)
{

View File

@ -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;

View File

@ -6,16 +6,16 @@
#include "syslog_output.h"
#include <FindDirectory.h>
#include <Path.h>
#include <driver_settings.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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[] = {

View File

@ -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*)"<DROP>", 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*)"<DROP>", 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)
{

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.
*/
#include <syslog_daemon.h>
#include <TLS.h>
#include <syslog.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <launch.h>
#include <syslog_daemon.h>
#include <TLS.h>
#include <util/KMessage.h>
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

View File

@ -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 ;

View File

@ -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 <syslog_daemon.h>
#include <OS.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
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));