2021-04-02 02:32:39 +00:00
|
|
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
|
|
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
|
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
|
|
│ │
|
|
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
|
|
|
│ │
|
|
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
2021-09-28 05:58:51 +00:00
|
|
|
#include "libc/sock/syslog.h"
|
2022-11-05 01:19:05 +00:00
|
|
|
#include "libc/calls/blockcancel.internal.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
#include "libc/calls/calls.h"
|
2022-08-13 20:11:56 +00:00
|
|
|
#include "libc/calls/struct/timespec.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
#include "libc/calls/weirdtypes.h"
|
2021-04-02 02:32:39 +00:00
|
|
|
#include "libc/dce.h"
|
|
|
|
#include "libc/errno.h"
|
2022-08-13 20:11:56 +00:00
|
|
|
#include "libc/intrin/safemacros.internal.h"
|
2021-04-02 02:32:39 +00:00
|
|
|
#include "libc/log/internal.h"
|
2022-04-12 06:35:48 +00:00
|
|
|
#include "libc/macros.internal.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
#include "libc/nt/events.h"
|
|
|
|
#include "libc/nt/runtime.h"
|
|
|
|
#include "libc/sock/sock.h"
|
2022-08-06 10:51:50 +00:00
|
|
|
#include "libc/sock/struct/sockaddr.h"
|
2023-09-02 03:49:13 +00:00
|
|
|
#include "libc/stdio/dprintf.h"
|
2021-04-02 02:32:39 +00:00
|
|
|
#include "libc/stdio/stdio.h"
|
|
|
|
#include "libc/str/str.h"
|
2021-09-28 05:58:51 +00:00
|
|
|
#include "libc/sysv/consts/af.h"
|
|
|
|
#include "libc/sysv/consts/clock.h"
|
|
|
|
#include "libc/sysv/consts/log.h"
|
|
|
|
#include "libc/sysv/consts/o.h"
|
|
|
|
#include "libc/sysv/consts/sock.h"
|
2024-05-05 06:05:36 +00:00
|
|
|
#include "libc/time.h"
|
2021-04-02 02:32:39 +00:00
|
|
|
|
|
|
|
/* Note: log_facility should be initialized with LOG_USER by default,
|
|
|
|
* but since LOG_USER is not a constant value, we cannot initialize it
|
|
|
|
* here. Set it to -1 to force the public functions to call __initlog()
|
|
|
|
* for the first time.
|
|
|
|
*/
|
|
|
|
static int log_facility = -1;
|
2022-04-12 06:35:48 +00:00
|
|
|
static char16_t log_ident[32];
|
2021-04-02 02:32:39 +00:00
|
|
|
static int log_opt;
|
|
|
|
static int log_mask;
|
2021-09-28 05:58:51 +00:00
|
|
|
static uint16_t log_id; /* Used for Windows EvtID */
|
2021-04-02 02:32:39 +00:00
|
|
|
static int64_t log_fd = -1;
|
|
|
|
|
2022-04-18 15:54:42 +00:00
|
|
|
static const char *const kLogPaths[] = {
|
|
|
|
"/dev/log",
|
|
|
|
// "/var/run/log", // TODO: Help with XNU and FreeBSD.
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct sockaddr_un log_addr = {AF_UNIX, "/dev/log"};
|
2021-04-02 02:32:39 +00:00
|
|
|
|
2021-09-28 05:58:51 +00:00
|
|
|
static int64_t Time(int64_t *tp) {
|
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
|
if (tp)
|
|
|
|
*tp = ts.tv_sec;
|
|
|
|
return ts.tv_sec;
|
|
|
|
}
|
2021-04-02 02:32:39 +00:00
|
|
|
|
|
|
|
static void __initlog() {
|
|
|
|
log_ident[0] = '\0';
|
|
|
|
log_opt = LOG_ODELAY;
|
|
|
|
log_facility = LOG_USER;
|
2021-09-28 05:58:51 +00:00
|
|
|
log_mask = LOG_PRI(0xff); // Initially use max verbosity
|
2021-04-02 02:32:39 +00:00
|
|
|
log_fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
forceinline int is_lost_conn(int e) {
|
2021-09-28 05:58:51 +00:00
|
|
|
return (e == ECONNREFUSED) || (e == ECONNRESET) || (e == ENOTCONN) ||
|
|
|
|
(e == EPIPE);
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __openlog() {
|
2022-04-18 15:54:42 +00:00
|
|
|
int i;
|
2021-04-02 02:32:39 +00:00
|
|
|
if (IsWindows()) {
|
2022-04-12 06:35:48 +00:00
|
|
|
log_fd = RegisterEventSource(NULL, log_ident);
|
2021-04-02 02:32:39 +00:00
|
|
|
} else {
|
2021-09-28 05:58:51 +00:00
|
|
|
log_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
2021-04-02 02:32:39 +00:00
|
|
|
if (log_fd >= 0) {
|
2022-04-18 15:54:42 +00:00
|
|
|
for (i = 0; i < ARRAYLEN(kLogPaths); ++i) {
|
|
|
|
strcpy(log_addr.sun_path, kLogPaths[i]);
|
|
|
|
if (!connect(log_fd, (void *)&log_addr, sizeof(log_addr))) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-28 05:58:51 +00:00
|
|
|
}
|
2022-04-18 15:54:42 +00:00
|
|
|
printf("ERR: connect(openlog) failed: %s (errno=%d)\n", strerror(errno),
|
|
|
|
errno);
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a log message which will be distributed by syslogd
|
|
|
|
*
|
|
|
|
* Note: no errors are reported if an error occurred while logging
|
|
|
|
* the message.
|
|
|
|
*
|
|
|
|
* @param priority is a bitmask containing the facility value and
|
|
|
|
* the level value. If no facility value is ORed into priority,
|
|
|
|
* then the default value set by openlog() is used.
|
|
|
|
* it set to NULL, the program name is used.
|
2021-09-28 05:58:51 +00:00
|
|
|
* Level is one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
|
2021-04-02 02:32:39 +00:00
|
|
|
* LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
|
|
|
|
* @param message the format of the message to be processed by vprintf()
|
|
|
|
* @param ap the va_list of arguments to be applied to the message
|
|
|
|
* @asyncsignalsafe
|
|
|
|
*/
|
|
|
|
void vsyslog(int priority, const char *message, va_list ap) {
|
2021-09-28 05:58:51 +00:00
|
|
|
char timebuf[16]; /* Store formatted time */
|
2021-04-02 02:32:39 +00:00
|
|
|
time_t now;
|
|
|
|
struct tm tm;
|
|
|
|
char buf[1024];
|
|
|
|
int errno_save = errno; /* Save current errno */
|
|
|
|
int pid;
|
|
|
|
int l, l2;
|
|
|
|
int hlen; /* If LOG_CONS is specified, use to store the point in
|
|
|
|
* the header message after the timestamp */
|
Make improvements
- We now serialize the file descriptor table when spawning / executing
processes on Windows. This means you can now inherit more stuff than
just standard i/o. It's needed by bash, which duplicates the console
to file descriptor #255. We also now do a better job serializing the
environment variables, so you're less likely to encounter E2BIG when
using your bash shell. We also no longer coerce environ to uppercase
- execve() on Windows now remotely controls its parent process to make
them spawn a replacement for itself. Then it'll be able to terminate
immediately once the spawn succeeds, without having to linger around
for the lifetime as a shell process for proxying the exit code. When
process worker thread running in the parent sees the child die, it's
given a handle to the new child, to replace it in the process table.
- execve() and posix_spawn() on Windows will now provide CreateProcess
an explicit handle list. This allows us to remove handle locks which
enables better fork/spawn concurrency, with seriously correct thread
safety. Other codebases like Go use the same technique. On the other
hand fork() still favors the conventional WIN32 inheritence approach
which can be a little bit messy, but is *controlled* by guaranteeing
perfectly clean slates at both the spawning and execution boundaries
- sigset_t is now 64 bits. Having it be 128 bits was a mistake because
there's no reason to use that and it's only supported by FreeBSD. By
using the system word size, signal mask manipulation on Windows goes
very fast. Furthermore @asyncsignalsafe funcs have been rewritten on
Windows to take advantage of signal masking, now that it's much more
pleasant to use.
- All the overlapped i/o code on Windows has been rewritten for pretty
good signal and cancelation safety. We're now able to ensure overlap
data structures are cleaned up so long as you don't longjmp() out of
out of a signal handler that interrupted an i/o operation. Latencies
are also improved thanks to the removal of lots of "busy wait" code.
Waits should be optimal for everything except poll(), which shall be
the last and final demon we slay in the win32 i/o horror show.
- getrusage() on Windows is now able to report RUSAGE_CHILDREN as well
as RUSAGE_SELF, thanks to aggregation in the process manager thread.
2023-10-08 12:36:18 +00:00
|
|
|
BLOCK_CANCELATION;
|
2021-04-02 02:32:39 +00:00
|
|
|
if (log_fd < 0)
|
|
|
|
__openlog();
|
|
|
|
if (!(priority & LOG_FACMASK))
|
|
|
|
priority |= log_facility;
|
|
|
|
/* Build the time string */
|
2021-09-28 05:58:51 +00:00
|
|
|
now = Time(NULL);
|
2021-04-02 02:32:39 +00:00
|
|
|
gmtime_r(&now, &tm);
|
|
|
|
strftime(timebuf, sizeof(timebuf), "%b %e %T", &tm);
|
|
|
|
pid = (log_opt & LOG_PID) ? getpid() : 0;
|
|
|
|
/* This is a clever trick to optionally include "[<pid>]"
|
|
|
|
* only if pid != 0. When pid==0, the while "[%.0d]" is skipped:
|
|
|
|
* %s%.0d%s -> String, pidValue, String
|
|
|
|
* Each of those %s:
|
2021-09-28 05:58:51 +00:00
|
|
|
* - if pid == 0 -> !pid is true (1), so "[" + 1 points to the
|
2021-04-02 02:32:39 +00:00
|
|
|
* NULL terminator after the "[".
|
|
|
|
* - if pid != 0 -> !pid is false (0), so the string printed is
|
|
|
|
* the "[".
|
|
|
|
*/
|
|
|
|
l = snprintf(buf, sizeof(buf), "<%d>%s ", priority, timebuf);
|
|
|
|
hlen = l;
|
2022-04-12 06:35:48 +00:00
|
|
|
l += snprintf(buf + l, sizeof(buf) - l, "%hs%s%.0d%s: ", log_ident,
|
|
|
|
"[" + !pid, pid, "]" + !pid);
|
2021-04-02 02:32:39 +00:00
|
|
|
errno = errno_save;
|
|
|
|
/* Append user message */
|
2021-09-28 05:58:51 +00:00
|
|
|
l2 = vsnprintf(buf + l, sizeof(buf) - l, message, ap);
|
2021-04-02 02:32:39 +00:00
|
|
|
if (l2 >= 0) {
|
|
|
|
if (l2 >= sizeof(buf) - l) {
|
|
|
|
l = sizeof(buf) - 1;
|
|
|
|
} else {
|
|
|
|
l += l2;
|
|
|
|
}
|
2021-09-28 05:58:51 +00:00
|
|
|
if (buf[l - 1] != '\n') {
|
2021-04-02 02:32:39 +00:00
|
|
|
buf[l++] = '\n';
|
|
|
|
}
|
|
|
|
if (!IsWindows()) {
|
2021-09-28 05:58:51 +00:00
|
|
|
/* Unix:
|
2021-04-02 02:32:39 +00:00
|
|
|
* - First try to send it to syslogd
|
|
|
|
* - If fails and LOG_CONS is provided, writes to /dev/console
|
|
|
|
*/
|
2022-11-05 01:19:05 +00:00
|
|
|
if (send(log_fd, buf, l, 0) < 0 &&
|
|
|
|
(!is_lost_conn(errno) ||
|
|
|
|
connect(log_fd, (void *)&log_addr, sizeof(log_addr)) < 0 ||
|
|
|
|
send(log_fd, buf, l, 0) < 0) &&
|
|
|
|
(log_opt & LOG_CONS)) {
|
|
|
|
int fd = open("/dev/console", O_WRONLY | O_NOCTTY);
|
2021-04-02 02:32:39 +00:00
|
|
|
if (fd >= 0) {
|
2022-11-05 01:19:05 +00:00
|
|
|
dprintf(fd, "%.*s", l - hlen, buf + hlen);
|
2021-04-02 02:32:39 +00:00
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
uint16_t evtType;
|
|
|
|
uint32_t evtID;
|
2021-09-28 05:58:51 +00:00
|
|
|
const char *bufArr[] = {
|
|
|
|
&buf[hlen]}; /* Only print the message without time*/
|
|
|
|
/* Windows only have 3 usable event types
|
2021-04-02 02:32:39 +00:00
|
|
|
* Event ID are not supported
|
2021-09-28 05:58:51 +00:00
|
|
|
* For more information on message types and event IDs, see:
|
2021-04-02 02:32:39 +00:00
|
|
|
* https://docs.microsoft.com/en-us/windows/win32/eventlog/event-identifiers
|
|
|
|
*/
|
|
|
|
priority &= LOG_PRIMASK; // Remove facility from the priority field
|
2021-09-28 05:58:51 +00:00
|
|
|
if (priority == LOG_EMERG || priority == LOG_ALERT ||
|
2021-04-02 02:32:39 +00:00
|
|
|
priority == LOG_CRIT) {
|
|
|
|
evtType = EVENTLOG_ERROR_TYPE;
|
|
|
|
evtID = 0xe << 28 | (LOG_USER) << 16;
|
|
|
|
} else if (priority == LOG_WARNING) {
|
|
|
|
evtType = EVENTLOG_WARNING_TYPE;
|
|
|
|
evtID = 0xa << 28 | (LOG_USER) << 16;
|
|
|
|
} else {
|
|
|
|
/* LOG_NOTICE, LOG_INFO, LOG_DEBUG */
|
|
|
|
evtType = EVENTLOG_INFORMATION_TYPE;
|
|
|
|
evtID = 0x6 << 28 | (LOG_USER) << 16;
|
|
|
|
}
|
2021-09-28 05:58:51 +00:00
|
|
|
ReportEventA(log_fd, evtType, /* Derived from priority */
|
|
|
|
0 /* Category unsupported */, evtID, /* Unsupported */
|
|
|
|
NULL, /* User SID */
|
|
|
|
1, /* Number of strings */
|
|
|
|
0, /* Raw data size */
|
|
|
|
bufArr, /* String(s) */
|
|
|
|
NULL /* Arguments */);
|
2021-04-02 02:32:39 +00:00
|
|
|
++log_id;
|
|
|
|
}
|
2022-06-09 03:01:28 +00:00
|
|
|
if (log_opt & LOG_PERROR) {
|
|
|
|
dprintf(2, "%.*s", l - hlen, buf + hlen);
|
|
|
|
}
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
Make improvements
- We now serialize the file descriptor table when spawning / executing
processes on Windows. This means you can now inherit more stuff than
just standard i/o. It's needed by bash, which duplicates the console
to file descriptor #255. We also now do a better job serializing the
environment variables, so you're less likely to encounter E2BIG when
using your bash shell. We also no longer coerce environ to uppercase
- execve() on Windows now remotely controls its parent process to make
them spawn a replacement for itself. Then it'll be able to terminate
immediately once the spawn succeeds, without having to linger around
for the lifetime as a shell process for proxying the exit code. When
process worker thread running in the parent sees the child die, it's
given a handle to the new child, to replace it in the process table.
- execve() and posix_spawn() on Windows will now provide CreateProcess
an explicit handle list. This allows us to remove handle locks which
enables better fork/spawn concurrency, with seriously correct thread
safety. Other codebases like Go use the same technique. On the other
hand fork() still favors the conventional WIN32 inheritence approach
which can be a little bit messy, but is *controlled* by guaranteeing
perfectly clean slates at both the spawning and execution boundaries
- sigset_t is now 64 bits. Having it be 128 bits was a mistake because
there's no reason to use that and it's only supported by FreeBSD. By
using the system word size, signal mask manipulation on Windows goes
very fast. Furthermore @asyncsignalsafe funcs have been rewritten on
Windows to take advantage of signal masking, now that it's much more
pleasant to use.
- All the overlapped i/o code on Windows has been rewritten for pretty
good signal and cancelation safety. We're now able to ensure overlap
data structures are cleaned up so long as you don't longjmp() out of
out of a signal handler that interrupted an i/o operation. Latencies
are also improved thanks to the removal of lots of "busy wait" code.
Waits should be optimal for everything except poll(), which shall be
the last and final demon we slay in the win32 i/o horror show.
- getrusage() on Windows is now able to report RUSAGE_CHILDREN as well
as RUSAGE_SELF, thanks to aggregation in the process manager thread.
2023-10-08 12:36:18 +00:00
|
|
|
ALLOW_CANCELATION;
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets log priority mask
|
|
|
|
*
|
2021-09-28 05:58:51 +00:00
|
|
|
* Modifies the log priority mask that determines which calls to
|
2021-04-02 02:32:39 +00:00
|
|
|
* syslog() may be logged.
|
|
|
|
* Log priority values are LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
|
2021-09-28 05:58:51 +00:00
|
|
|
* LOG_WARNING, LOG_NOTICE, LOG_INFO, and LOG_DEBUG.
|
2021-04-02 02:32:39 +00:00
|
|
|
*
|
|
|
|
* @param mask the new priority mask to use by syslog()
|
|
|
|
* @return the previous log priority mask
|
|
|
|
* @asyncsignalsafe
|
|
|
|
*/
|
|
|
|
int setlogmask(int maskpri) {
|
|
|
|
int ret;
|
2022-11-05 01:19:05 +00:00
|
|
|
if (log_facility == -1)
|
|
|
|
__initlog();
|
2021-04-02 02:32:39 +00:00
|
|
|
ret = log_mask;
|
|
|
|
if (maskpri)
|
|
|
|
log_mask = LOG_PRI(maskpri);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens a connection to the system logger
|
|
|
|
*
|
2021-09-28 05:58:51 +00:00
|
|
|
* Calling this function before calling syslog() is optional and
|
|
|
|
* only allow customizing the identity, options and facility of
|
2021-04-02 02:32:39 +00:00
|
|
|
* the messages logged.
|
|
|
|
*
|
|
|
|
* @param ident a string that prepends every logged message. If
|
|
|
|
* it set to NULL, the program name is used.
|
|
|
|
* @param opt specifies flags which control the operation of openlog().
|
|
|
|
* Only the following flags are supported:
|
|
|
|
* LOG_CONS = Write directly to the system console if there is
|
|
|
|
* an error while sending to the system logger.
|
|
|
|
* LOG_NDELAY = Open the connection with the system logger
|
|
|
|
* immediately instead of waiting for the first
|
|
|
|
* message to be logged.
|
|
|
|
* LOG_ODELAY = The converse of LOG_NDELAY.
|
|
|
|
* LOG_PERROR = Also log the message to stderr.
|
|
|
|
* LOG_PID = Include the caller's PID with each message
|
|
|
|
* @param facility specifies the default facitlity value that defines
|
|
|
|
* what kind of program is logging the message.
|
|
|
|
* Possible values are: LOG_AUTH, LOG_AUTHPRIV,
|
|
|
|
* LOG_CRON, LOG_DAEMON, LOG_FTP, LOG_LOCAL0 through LOG_LOCAL7,
|
|
|
|
* LOG_LPR, LOG_MAIL, LOG_NEWS, LOG_SYSLOG, LOG_USER (default),
|
|
|
|
* LOG_UUCP.
|
|
|
|
* @asyncsignalsafe
|
|
|
|
*/
|
|
|
|
void openlog(const char *ident, int opt, int facility) {
|
Make improvements
- We now serialize the file descriptor table when spawning / executing
processes on Windows. This means you can now inherit more stuff than
just standard i/o. It's needed by bash, which duplicates the console
to file descriptor #255. We also now do a better job serializing the
environment variables, so you're less likely to encounter E2BIG when
using your bash shell. We also no longer coerce environ to uppercase
- execve() on Windows now remotely controls its parent process to make
them spawn a replacement for itself. Then it'll be able to terminate
immediately once the spawn succeeds, without having to linger around
for the lifetime as a shell process for proxying the exit code. When
process worker thread running in the parent sees the child die, it's
given a handle to the new child, to replace it in the process table.
- execve() and posix_spawn() on Windows will now provide CreateProcess
an explicit handle list. This allows us to remove handle locks which
enables better fork/spawn concurrency, with seriously correct thread
safety. Other codebases like Go use the same technique. On the other
hand fork() still favors the conventional WIN32 inheritence approach
which can be a little bit messy, but is *controlled* by guaranteeing
perfectly clean slates at both the spawning and execution boundaries
- sigset_t is now 64 bits. Having it be 128 bits was a mistake because
there's no reason to use that and it's only supported by FreeBSD. By
using the system word size, signal mask manipulation on Windows goes
very fast. Furthermore @asyncsignalsafe funcs have been rewritten on
Windows to take advantage of signal masking, now that it's much more
pleasant to use.
- All the overlapped i/o code on Windows has been rewritten for pretty
good signal and cancelation safety. We're now able to ensure overlap
data structures are cleaned up so long as you don't longjmp() out of
out of a signal handler that interrupted an i/o operation. Latencies
are also improved thanks to the removal of lots of "busy wait" code.
Waits should be optimal for everything except poll(), which shall be
the last and final demon we slay in the win32 i/o horror show.
- getrusage() on Windows is now able to report RUSAGE_CHILDREN as well
as RUSAGE_SELF, thanks to aggregation in the process manager thread.
2023-10-08 12:36:18 +00:00
|
|
|
BLOCK_CANCELATION;
|
2022-11-05 01:19:05 +00:00
|
|
|
if (log_facility == -1)
|
|
|
|
__initlog();
|
|
|
|
if (!ident)
|
|
|
|
ident = firstnonnull(program_invocation_short_name, "unknown");
|
2022-04-12 06:35:48 +00:00
|
|
|
tprecode8to16(log_ident, ARRAYLEN(log_ident), ident);
|
2021-04-02 02:32:39 +00:00
|
|
|
log_opt = opt;
|
|
|
|
log_facility = facility;
|
|
|
|
log_id = 0;
|
2021-09-28 05:58:51 +00:00
|
|
|
if ((opt & LOG_NDELAY) && log_fd < 0)
|
|
|
|
__openlog();
|
Make improvements
- We now serialize the file descriptor table when spawning / executing
processes on Windows. This means you can now inherit more stuff than
just standard i/o. It's needed by bash, which duplicates the console
to file descriptor #255. We also now do a better job serializing the
environment variables, so you're less likely to encounter E2BIG when
using your bash shell. We also no longer coerce environ to uppercase
- execve() on Windows now remotely controls its parent process to make
them spawn a replacement for itself. Then it'll be able to terminate
immediately once the spawn succeeds, without having to linger around
for the lifetime as a shell process for proxying the exit code. When
process worker thread running in the parent sees the child die, it's
given a handle to the new child, to replace it in the process table.
- execve() and posix_spawn() on Windows will now provide CreateProcess
an explicit handle list. This allows us to remove handle locks which
enables better fork/spawn concurrency, with seriously correct thread
safety. Other codebases like Go use the same technique. On the other
hand fork() still favors the conventional WIN32 inheritence approach
which can be a little bit messy, but is *controlled* by guaranteeing
perfectly clean slates at both the spawning and execution boundaries
- sigset_t is now 64 bits. Having it be 128 bits was a mistake because
there's no reason to use that and it's only supported by FreeBSD. By
using the system word size, signal mask manipulation on Windows goes
very fast. Furthermore @asyncsignalsafe funcs have been rewritten on
Windows to take advantage of signal masking, now that it's much more
pleasant to use.
- All the overlapped i/o code on Windows has been rewritten for pretty
good signal and cancelation safety. We're now able to ensure overlap
data structures are cleaned up so long as you don't longjmp() out of
out of a signal handler that interrupted an i/o operation. Latencies
are also improved thanks to the removal of lots of "busy wait" code.
Waits should be optimal for everything except poll(), which shall be
the last and final demon we slay in the win32 i/o horror show.
- getrusage() on Windows is now able to report RUSAGE_CHILDREN as well
as RUSAGE_SELF, thanks to aggregation in the process manager thread.
2023-10-08 12:36:18 +00:00
|
|
|
ALLOW_CANCELATION;
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a log message which will be distributed by syslogd
|
|
|
|
*
|
|
|
|
* Note: no errors are reported if an error occurred while logging
|
|
|
|
* the message.
|
|
|
|
*
|
|
|
|
* @param priority is a bitmask containing the facility value and
|
|
|
|
* the level value. If no facility value is ORed into priority,
|
|
|
|
* then the default value set by openlog() is used.
|
|
|
|
* it set to NULL, the program name is used.
|
2021-09-28 05:58:51 +00:00
|
|
|
* Level is one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
|
2021-04-02 02:32:39 +00:00
|
|
|
* LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
|
|
|
|
* @param message the message formatted using the same rules as printf()
|
|
|
|
* @asyncsignalsafe
|
|
|
|
*/
|
|
|
|
void syslog(int priority, const char *message, ...) {
|
|
|
|
va_list ap;
|
|
|
|
if (log_facility == -1) {
|
|
|
|
__initlog();
|
|
|
|
}
|
|
|
|
if (LOG_PRI(priority) <= log_mask) {
|
|
|
|
va_start(ap, message);
|
|
|
|
vsyslog(priority, message, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Closes the file descriptor being used to write to the system logger
|
|
|
|
*
|
|
|
|
* Use of closelog is optional
|
|
|
|
* @asyncsignalsafe
|
|
|
|
*/
|
|
|
|
void closelog(void) {
|
|
|
|
if (log_facility == -1) {
|
|
|
|
__initlog();
|
|
|
|
}
|
2022-11-05 01:19:05 +00:00
|
|
|
if (log_fd != -1) {
|
|
|
|
if (IsWindows()) {
|
|
|
|
DeregisterEventSource(log_fd);
|
|
|
|
} else {
|
|
|
|
close(log_fd);
|
|
|
|
}
|
|
|
|
log_fd = -1;
|
2021-04-02 02:32:39 +00:00
|
|
|
}
|
|
|
|
}
|