G
Gregory Starck
Hello,
I'm having what seems to be a deadlock in syslog with the code (wich
comes from a project I'm working on, but I've reduced the test case to
its minimum) I put at the end of this messsage.
It must be compiled with -lpthread. (so the fork could be also a
possible cause of what I'm mentionning).
The "bug" does not occur every times. So you should maybe launch the
prog a few times before the block occurs.
Is there someone knowing the true about this fact :
Is it from my code ? or is it a bug within syslog ???
or something else ?
And are they any technics (or patch for syslog ?) wich could resolve the
problem ??
Ho, btw, I'm using Linux 2.4.21, and it's a Mandrake 9.1.
Thanks for your responses.
Greg.
Here is the code :
##################################################################################
#include <sys/types.h>
#include <signal.h>
#include <syslog.h>
#include <stdio.h>
#include <errno.h>
void handler_sigchild (int signal_value);
void
set_father_signals (void)
{
struct sigaction
sigchild;
sigset_t
sigsblocked;
sigchild.sa_handler = handler_sigchild;
sigchild.sa_flags = 0;
if (sigfillset (&sigchild.sa_mask) == -1)
{
printf ("set_father_signals: a sigfillset() failed. err = %s
!\n", strerror (errno));
}
if ((sigfillset (&sigsblocked) == -1) /* and we respond
only to those */
|| (sigdelset (&sigsblocked, SIGCHLD) == -1))
{
printf ("set_father_signals: could not fill blocked signals.
err = %s !\n", strerror (errno));
}
if (sigprocmask (SIG_SETMASK, &sigsblocked, NULL) == -1)
{
printf ("set_father_signals: could not set blocked signals. err
= %s !\n", strerror (errno));
}
if (sigaction (SIGCHLD, &sigchild, NULL) == -1)
{
printf ("kern_set_father_signals: a sigaction() failed. err =
%s !\n", strerror (errno));
}
}
int main ( int argc, char * argv [] )
{
pid_t pid;
openlog ("testbug3", LOG_PID | LOG_CONS, LOG_DAEMON);
set_father_signals ();
switch (pid = fork ())
{
case -1:
printf ("Error while forking : %s\n", strerror (errno));
break;
case 0 : /* in child */
exit (0); /* just return immediately */
default : /* in father */
printf ("father: after fork, before syslog\n");
fflush (stdout);
syslog (LOG_INFO, "TRACE: child's pid = %lu", pid);
printf ("father: after fork, after syslog\n");
fflush (stdout);
}
closelog ();
wait (NULL); /* wait for the child */
printf ("exiting\n");
fflush (stdout);
}
void handler_sigchild (int sig)
{
printf ("In sighandle, before syslog\n");
fflush (stdout);
syslog (LOG_INFO, "received a SIGCHLD");
printf ("In sighandle, after syslog\n");
fflush (stdout);
}
#########################################################################
I'm having what seems to be a deadlock in syslog with the code (wich
comes from a project I'm working on, but I've reduced the test case to
its minimum) I put at the end of this messsage.
It must be compiled with -lpthread. (so the fork could be also a
possible cause of what I'm mentionning).
The "bug" does not occur every times. So you should maybe launch the
prog a few times before the block occurs.
Is there someone knowing the true about this fact :
Is it from my code ? or is it a bug within syslog ???
or something else ?
And are they any technics (or patch for syslog ?) wich could resolve the
problem ??
Ho, btw, I'm using Linux 2.4.21, and it's a Mandrake 9.1.
Thanks for your responses.
Greg.
Here is the code :
##################################################################################
#include <sys/types.h>
#include <signal.h>
#include <syslog.h>
#include <stdio.h>
#include <errno.h>
void handler_sigchild (int signal_value);
void
set_father_signals (void)
{
struct sigaction
sigchild;
sigset_t
sigsblocked;
sigchild.sa_handler = handler_sigchild;
sigchild.sa_flags = 0;
if (sigfillset (&sigchild.sa_mask) == -1)
{
printf ("set_father_signals: a sigfillset() failed. err = %s
!\n", strerror (errno));
}
if ((sigfillset (&sigsblocked) == -1) /* and we respond
only to those */
|| (sigdelset (&sigsblocked, SIGCHLD) == -1))
{
printf ("set_father_signals: could not fill blocked signals.
err = %s !\n", strerror (errno));
}
if (sigprocmask (SIG_SETMASK, &sigsblocked, NULL) == -1)
{
printf ("set_father_signals: could not set blocked signals. err
= %s !\n", strerror (errno));
}
if (sigaction (SIGCHLD, &sigchild, NULL) == -1)
{
printf ("kern_set_father_signals: a sigaction() failed. err =
%s !\n", strerror (errno));
}
}
int main ( int argc, char * argv [] )
{
pid_t pid;
openlog ("testbug3", LOG_PID | LOG_CONS, LOG_DAEMON);
set_father_signals ();
switch (pid = fork ())
{
case -1:
printf ("Error while forking : %s\n", strerror (errno));
break;
case 0 : /* in child */
exit (0); /* just return immediately */
default : /* in father */
printf ("father: after fork, before syslog\n");
fflush (stdout);
syslog (LOG_INFO, "TRACE: child's pid = %lu", pid);
printf ("father: after fork, after syslog\n");
fflush (stdout);
}
closelog ();
wait (NULL); /* wait for the child */
printf ("exiting\n");
fflush (stdout);
}
void handler_sigchild (int sig)
{
printf ("In sighandle, before syslog\n");
fflush (stdout);
syslog (LOG_INFO, "received a SIGCHLD");
printf ("In sighandle, after syslog\n");
fflush (stdout);
}
#########################################################################