Package: syslog-ng Version: 2.0rc3-1 Severity: important Tags: patch
(This is the same problem reported against syslog-ng in Gentoo at https://bugs.gentoo.org/show_bug.cgi?id=154465 -- this contains a patch which fixes the problem with a similar approach to that taken in sysklogd.) When syslog-ng writes to a tty under Linux, for example as a result of a usertty directive, the write syscall to /dev/ttyN can ocassionally block indefinitely. One situation when this occurs is when the user has set XOFF (perhaps with Ctrl-S or Scroll Lock). Aside from the fact that this obvious prevents any further log messages from being written, /dev/log's buffer eventually fills up causing other programs to block writing to /dev/log. In extremis, this can render a machine inaccesible when ssh, etc., all block preventing access. Reproducible: Always Steps to Reproduce: 1. Check that there is a usertty("*") directive for (say) kern.emerg logs 2. Ensure syslog-ng is running 3. On console, press Scroll Lock 4. Log something, e.g. logger -p kern.emerg 'Foo'. 5. Repeat #4 many times; eventually it will hang trying to log -- System Information: Debian Release: testing/unstable APT prefers unstable APT policy: (500, 'unstable'), (500, 'stable') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.15.2-3 Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Versions of packages syslog-ng depends on: ii libc6 2.3.6.ds1-4 GNU C Library: Shared libraries ii util-linux 2.12r-11 Miscellaneous system utilities Versions of packages syslog-ng recommends: ii logrotate 3.7.1-3 Log rotation utility -- no debconf information
--- src/afuser.c.orig 2006-11-08 12:36:11.886371656 +0000 +++ src/afuser.c 2006-11-08 13:13:32.133802280 +0000 @@ -27,6 +27,8 @@ #include <string.h> #include <fcntl.h> #include <unistd.h> +#include <signal.h> +#include <setjmp.h> typedef struct _AFUserDestDriver { @@ -46,6 +48,14 @@ return TRUE; } +static sigjmp_buf jmp; + +static void alarmproc() +{ + signal(SIGALRM, alarmproc); + siglongjmp(jmp, 1); +} + static void afuser_dd_queue(LogPipe *s, LogMessage *msg, gint path_flags) { @@ -77,7 +87,15 @@ fd = open(line, O_NOCTTY | O_APPEND | O_WRONLY); if (fd != -1) { - write(fd, buf, strlen(buf)); + if (sigsetjmp(jmp, 1) == 0) + { + signal(SIGALRM, alarmproc); + alarm(15); + write(fd, buf, strlen(buf)); + } + + alarm(0); + signal(SIGALRM, SIG_DFL); close(fd); } }