Python signal delivery under BSD 4.4

Donn Cave donn at u.washington.edu
Wed Aug 13 14:04:12 EDT 2003


In article <m3bruuk080.fsf at drizzle.com>,
 "Elf M. Sternberg" <elf at drizzle.com> wrote:
> I'm having a devil of a time with signal handling under BSD 4.4 with
> Python and I was hoping that this might ring a bell with someone.  Using
> the Webware Application Server (a multi-threaded Python application), I
> fork off a process to run independently and do some heavy-duty multi-
> threaded I/O churning.  The process is launched with os.spawnvp().
> 
>         The user may, at any time, elect to terminate this process
> before it reaches its end.  I do that by having the Application Server
> send a SIGUSR1 signal to the process ID returned by os.spawnvp(), which
> so far has been reliably returned and stored in the appserver's session
> mananger.  So far, so good.
> 
>         This worked well under Python 2.1, where I used os.fork() instead
> of os.spawnvp().
> 
>         We have upgraded to Python 2.2.3 and it has mysteriously stopped
> working.  Processes launched off the appserver, whether using os.fork()
> or os.spawnvp(), are now completely deaf to signals.  Nothing gets its
> attention except, of course, SIGKILL.  Not when sent from the appserver,
> and not when sent from the shell, not even by root.
> 
>         If the process is launched from the command line, however, it
> is well-behaved and responds to signal reliably. 
> 
>         What gives?

Don't know.  Can you duplicate it in a simpler environment?
I'd like to run the following C program from spawnv, from a
Python program like

  import os
  import time
  import signal

  p = os.spawnv(os.P_NOWAIT, 'prsig', ['prsig'])
  time.sleep(1.0)
  os.kill(p, signal.SIGTERM)
  print 'process exit', os.waitpid(p, 0)

if you think that represents what you're doing.  This seems
to work as expected with Python 2.2 on a BSD platform (if
your "BSD 4.4" is actually NetBSD 1.6 or FreeBSD 5.1, I could
try that.)

The reasons I can think of in principle are
1.  handler set to SIG_IGN (if the child process is supposed
    to exit due to the default signal handler.)
2.  blocked via signal mask
3.  wrong process

   Donn Cave, donn at u.washington.edu/donn at drizzle.com

include <signal.h>
#include <stdio.h>
#include <string.h>

static void
handler(int sig)
{
        switch (sig) {
        case SIGALRM:
                fprintf(stderr, "caught SIGALRM\n");
                break;
        case SIGUSR1:
                fprintf(stderr, "caught SIGUSR1\n");
                break;
        default:
                fprintf(stderr, "caught %d\n", sig);
        }
        exit(0);
}

static void
prsig(int sig)
{
        struct sigaction sa;
        int status;
        memset(&sa, 0, sizeof(sa));
        status = sigaction(sig, 0, &sa);
        if (status == 0) {
                printf("sigaction {\n");
                printf("    sa_handler 0x%08x,\n", sa.sa_handler);
                printf("    sa_flags 0x%08x\n", sa.sa_flags);
                /* printf("    sa_mask 0x%08x\n", sa.sa_mask); */
                printf("}\n");
        } else {
                perror("sigaction query");
                exit(2);
        }
}

static void
prmask()
{
        sigset_t mask;
        int status;
        status = sigprocmask(SIG_SETMASK, 0, &mask);
        if (status == 0)
                fprintf(stdout, "mask 0x%lx\n", mask);
        else {
                perror("sigprocmask");
                exit(2);
        }
}

static void
sethandler(int sig, void (*hf)(int))
{
        struct sigaction sa;
        int status;
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = hf;
        status = sigaction(sig, &sa, 0);
        if (status == 0) {
        } else {
                perror("sigaction");
                exit(2);
        }
}

static void
pause()
{
        char buffer[4];
        read(0, buffer, 4);
}

int
main(int argc, char **argv)
{
        prsig(SIGUSR1);
        prmask();
        sethandler(SIGUSR1, handler);
        sethandler(SIGALRM, handler);
        alarm(3);
        pause();
        return 0;
}




More information about the Python-list mailing list