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? 8 3677
In article <m3************@drizzle.com>,
"Elf M. Sternberg" <el*@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, do**@u.washington.edu/do**@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;
}
Donn Cave <do**@u.washington.edu> writes: In article <m3************@drizzle.com>, "Elf M. Sternberg" <el*@drizzle.com> wrote:
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.
I'm sorry about the confusion. FreeBSD 4.4 is what we're
running where I work.
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)
I'm going to assume you meant 'SIGUSR1' here since that's what
you're catching in the C code you included.
In any event, your code worked as expected.
However, this variant worked as I've reported:
import os
import sys
import time
import signal
import thread
def do_it():
p = os.spawnv(os.P_NOWAIT, 'prsig', ['prsig'])
print >>sys.stderr, "Sleeping"
time.sleep(1.0)
os.kill(p, signal.SIGUSR1)
print 'process exit', os.waitpid(p, 0)
sys.exit()
thread.start_new_thread(do_it, ())
time.sleep(4.0)
Not only did it behave as I reported, but it slept the full four
seconds even though the sys.exit() call was made. This leads me to the
conclusion that something rather unusual is going on within Python's
threading module and the libc_r.a within FreeBSD4.4.
Right now, I just want a way to make signal delivery work.
Thanks for your help so far, though.
Elf
In article <m3************@drizzle.com>,
"Elf M. Sternberg" <el*@drizzle.com> wrote:
.... I'm going to assume you meant 'SIGUSR1' here since that's what you're catching in the C code you included.
Right, sorry.
However, this variant worked as I've reported:
[... forks from thread ]
I tried it from FreeBSD 5.1, using 2.2.2 built from ports,
and didn't see this problem. I believe 5.1 has a significantly
different thread implementation from 4.x, though.
Note that there is pthread_sigmask(3) with the same arguments as
sigprocmask(2), and Python's thread_pthread.h does appear to block
all signals that way when starting a new thread. That's a clue,
perhaps. If sigprocmask() didn't show any signals blocked, maybe
pthread_sigmask() would, or maybe at any rate you can set the
mask to 0 using one or the other of those functions.
Donn Cave, do**@u.washington.edu
On Wed, 13 Aug 2003, Donn Cave wrote: In article <m3************@drizzle.com>, "Elf M. Sternberg" <el*@drizzle.com> wrote:
However, this variant worked as I've reported: [... forks from thread ]
I tried it from FreeBSD 5.1, using 2.2.2 built from ports, and didn't see this problem. I believe 5.1 has a significantly different thread implementation from 4.x, though.
And later releases of FreeBSD 4.x have a number of bugfixes to the pthread
support, including some signal related changes. The 4.x pthread support
still has some issues though.
Elf refers to this working with Python 2.1 - I vaguely recall some changes
to Python's pthreads support to try and "harmonise" the behaviour across a
number of platforms, and signal delivery may have been affected such that
signals are only delivered to the primary thread. As this is only a vague
recollection, treat with caution...
Does building Python with the linuxthreads port, instead of FreeBSD's
native pthreads, behave as expected?
Note that there is pthread_sigmask(3) with the same arguments as sigprocmask(2), and Python's thread_pthread.h does appear to block all signals that way when starting a new thread. That's a clue, perhaps. If sigprocmask() didn't show any signals blocked, maybe pthread_sigmask() would, or maybe at any rate you can set the mask to 0 using one or the other of those functions.
I also recall Michael Hudson trying to get signal mask support working in
the presence of threads, but he could only get it to work on Linux. We
did eventually get a required fix to FreeBSD's libc_r committed (in the
4.7 timeframe I think), but Michael had given up by then and canned his
code.
--
Andrew I MacIntyre "These thoughts are mine alone..."
E-mail: an*****@bullseye.apana.org.au (pref) | Snail: PO Box 370 an*****@pcug.org.au (alt) | Belconnen ACT 2616
Web: http://www.andymac.org/ | Australia
Andrew MacIntyre <an*****@bullseye.apana.org.au> writes: I tried it from FreeBSD 5.1, using 2.2.2 built from ports, and didn't see this problem. I believe 5.1 has a significantly different thread implementation from 4.x, though.
And later releases of FreeBSD 4.x have a number of bugfixes to the pthread support, including some signal related changes. The 4.x pthread support still has some issues though.
I went and looked again at the evidence.
When calling the function with apply(), the child process spawned off
reports:
mask 0x0
When calling the function with thread.start_new_thread(), the child
process reports:
mask 0xfffefeff
So I think the two of you have more or less hit it squarely on the
head. Now, I just have to find a way around it... *Sigh*
Elf
Michael Hudson wrote: "Elf M. Sternberg" <el*@drizzle.com> writes:
Right now, I just want a way to make signal delivery work.
At some point, the threads implementation got changed so that new threads get their signal mask set to "block everything and it's cat" (there was a reason for this, but I'm not really sure what it was). As I see it, you have two options: 1) write a little C to unset the procmask after fork() but before execve() 2) only launch apps from the main thread.
Incidentally, these aren't far from the advice in "Pthreads Programming"
(by Nichols, Buttlar and Proulx Farrell -- O'Reilly) in Chapter 5, under
"Threads and Process Management". The authors are dealing with C issues,
not Python by any means, but still they conclude that "forking from a
multithreaded program is no picnic" and suggest 1) fork before you've
created any threads, and 2) consider the surrogate parent model (fork a
child process at init time, IPC with the child -- which remains single
threaded -- to delegate forking and execing on our behalf).
Alex
Alex Martelli <al*****@yahoo.com> writes: Incidentally, these aren't far from the advice in "Pthreads Programming" (by Nichols, Buttlar and Proulx Farrell -- O'Reilly) in Chapter 5, under "Threads and Process Management". The authors are dealing with C issues, not Python by any means, but still they conclude that "forking from a multithreaded program is no picnic" and suggest 1) fork before you've created any threads, and 2) consider the surrogate parent model (fork a child process at init time, IPC with the child -- which remains single threaded -- to delegate forking and execing on our behalf).
(1) wasn't really viable since the parent process is ruled by an
application server (Webware, in this case) and I have no desire to go
trolling through the guts of that excellent program to make it "work"
the way I want. I almost went with (2). But, fortunately, we're
developing a single-OS appliance and don't really care about
cross-platform compatibility, so I worked with the FreeBSD 4.4 "model"
of forking from multithreaded applications. It's fortunate that the
next call is an exec(); I'd hate to have to manage a forked copy of the
process with that one thread...
Elf
Quoth "Elf M. Sternberg" <el*@drizzle.com>:
| ... But, fortunately, we're
| developing a single-OS appliance and don't really care about
| cross-platform compatibility, so I worked with the FreeBSD 4.4 "model"
| of forking from multithreaded applications. It's fortunate that the
| next call is an exec(); I'd hate to have to manage a forked copy of the
| process with that one thread...
So, you resolved the problem and the spawnv child process can now
receive signals? Did you use sigprocmask() to clear the signal
mask? What is the FreeBSD 4.4 model of forking from multithreaded
applications? (And is it the same as the FreeBSD 4.7 model, 5.1, etc.?)
Donn Cave, do**@drizzle.com This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Antoon Pardon |
last post by:
I have had a look at the signal module and the example
and came to the conclusion that the example wont work
if you try to do this in a thread.
So is there a chance similar code will work in a...
|
by: Jorge |
last post by:
All,
I've got a process that creates some children and want to be alerted
when they die. To do this, the SIGCHLD signal is registered in the
process using sigaction to jump to a subprogram as...
|
by: lpw |
last post by:
I have dilligently reviewed FAQ-lite Section 3.2, "How do I pass a
pointer-to-member-function to a signal handler, X event callback, system
call that starts a thread/task, etc." The only...
|
by: Eric Boutin |
last post by:
Hi ! currently reading C docs, I think I'm reading docs about the stdc lib,
but I'm not shure.. it talks about signals, does *all* OS implement the
signal function, and use it well ? I mean.. I...
|
by: Ollie Cook |
last post by:
Hi,
I am having some difficulty with read(2) and interrupting signals. I
expect I am misunderstanding how the two work together, so would
appreciate some guidance.
I am trying to 'time out' a...
|
by: gnutuxy |
last post by:
Hi,
I am newbie in the Unix system programming and in learning phase.
I usually read the libc manual and then try to implement small
programs to test/check the learnt thing.
I read the libc...
|
by: Adrian Casey |
last post by:
I have a multi-threaded python application which uses pexpect to connect to
multiple systems concurrently. Each thread within my application is a
connection to a remote system. The problem is...
|
by: Grant Edwards |
last post by:
Could whoever is responsible for the gateway that is grabbing
my postings off of Usenet and e-mailing them out please fix the
headers in the mail messages so that I don't get the bounce
messages?...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
| |