|
Home > Archive > Unix Programming > April 2007 > about signals
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| Mr. X. 2007-04-18, 7:18 pm |
| Hello,
I want to do something like the following :
while (true)
{
if ( (pid = fork()) < 0) {
perror("fork error\n");
exit(1);
}
if (pid > 0) { /* parent */
...
}
else {
...
}
....
}
.....
If parent process doesn't wait for child to end , letting the child doing
its process on background,
what should I do instead (I want to understand the sigsuspend, sigprocmask,
etc ..., and why they are needed in order to block nor unblock child
termination signal).
Thanks 
| |
| Jens Thoms Toerring 2007-04-18, 7:18 pm |
| Mr. X. <no_spam_please@nospam_please.com> wrote:
> I want to do something like the following :
> while (true)
> {
> if ( (pid = fork()) < 0) {
> perror("fork error\n");
> exit(1);
> }
> if (pid > 0) { /* parent */
> ...
> }
> else {
> ...
> }
> ...
> }
> ....
> If parent process doesn't wait for child to end , letting the child doing
> its process on background,
If you don't want to wait() for the child to exit before you continue
in the parent you probably best install a handler for the SIGCHLD
signal and call wait() there. That way wait() will only be called
when the child is already dead, so it doesn't stop you from doing
other things while the child is still running, and the death of the
child gets acknowledged, so you don't get zombie processes.
> what should I do instead (I want to understand the sigsuspend, sigprocmask,
> etc ..., and why they are needed in order to block nor unblock child
> termination signal).
Why would you think you have to use those functions in this situation?
sigprocmask() just sets a new signal mask and with sigsuspend() you
actually put your process to sleep while waiting for one of the un-
blocked signals in the mask to come in. I don't see how this would
help you in _not_ waiting for the child to exit(). You could use them
for the other way round, i.e. to put your process to sleep until the
child dies and the SIGCHLD signal is raised.
The only situation I can come up with where you would use them is when
want no SIGCHLD signal to arrive for a certain time (but not lose it),
thus you could block it and then, when you're ready for the signal and
have nothing else to do, call sigsuspend() to receive it if it already
arrived or sleep until it comes in.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
| |
| Mr. X. 2007-04-18, 7:18 pm |
| > The only situation I can come up with where you would use them is when
> want no SIGCHLD signal to arrive for a certain time (but not lose it),
> thus you could block it and then, when you're ready for the signal and
> have nothing else to do, call sigsuspend() to receive it if it already
> arrived or sleep until it comes in.
>
> Regards, Jens
Let me understand something :
When I block SIGCHLD at a certain time,
and after some commands, I do : sigsuspend to receive it.
Is that mean that the SIGCHLD is keeped somewhere (in queue or something) ,
if it occured already,
till I call sigsuspend().
I need a tiny code sample, for using SIGCHLD & sigsuspend, please.
Thanks 
| |
| Jens Thoms Toerring 2007-04-18, 7:18 pm |
| Mr. X. <no_spam_please@nospam_please.com> wrote:
> Let me understand something :
> When I block SIGCHLD at a certain time,
> and after some commands, I do : sigsuspend to receive it.
> Is that mean that the SIGCHLD is keeped somewhere (in queue or something) ,
> if it occured already, till I call sigsuspend().
Yes, that's what blocking a signal is for - for just throwing it
away you would set the signal disposition to SIG_IGN. The re-
triction is that normally you shouldn't expect the queue for
each kind of signal to be larger that one element, so even if
e.g. three signals of a certain kind arrive while that signal
is blocked, you tyically will only get one when you unblock
the signal. Only for so-called real-time signals there is a
larger queue, but how many signals can get stored may vary
from system to system (and you should expect that the length
of the queue is rather short, POSIX requests a minimum length
of 32).
> I need a tiny code sample, for using SIGCHLD & sigsuspend, please.
Here we go:
sigset_t new_set, old_set; /* define two signal sets */
/* Set up 'new_set' for blocking of SIGCHLD */
sigemptyset( &new_set ); /* first clean it up */
sigaddset( &new_set, SIGCHLD );
/* Now add SIGCHLD to the list of signals that are blocked */
sigprocmask( SIG_BLOCK, &new_set, &old_set );
/* SIGCHLD is now blocked do something while its blocked */
.....
/* Now lets only react to a SIGCHLD signal, all others are blocked
since only SIGCHLD is set in 'new_set'. If a SIGCHLD was already
raised in the meantime the sigsuspend() call will return immedia-
tely, otherwise the process is put to sleep until SIGCHLD gets
raised. */
sigsuspend( &new_set )
/* To clean up after all this we finally set the signal mask back to
what it was before all these manipulations */
sigprocmask( SIG_SETMASK, &old_set, NULL );
Of course, you will have to install a signal handler for SIGCHLD
since by default the signal disposition for SIGCHLD is SIG_IGN,
but you don't want to ignore it here and in that case you need
a signal handler.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
| |
| Mr. X. 2007-04-18, 7:18 pm |
| > Here we go:
>
> sigset_t new_set, old_set; /* define two signal sets */
>
> /* Set up 'new_set' for blocking of SIGCHLD */
>
> sigemptyset( &new_set ); /* first clean it up */
> sigaddset( &new_set, SIGCHLD );
.... someone told me it should be the opposite :
sigfillset(&new_set);
sigdlset(&new_set);
sigprocmask( SIG_BLOCK, &new_set, &old_set );
Why so ?
> /* Now add SIGCHLD to the list of signals that are blocked */
>
> sigprocmask( SIG_BLOCK, &new_set, &old_set );
>
> /* SIGCHLD is now blocked do something while its blocked */
>
> ....
>
> /* Now lets only react to a SIGCHLD signal, all others are blocked
> since only SIGCHLD is set in 'new_set'. If a SIGCHLD was already
> raised in the meantime the sigsuspend() call will return immedia-
> tely, otherwise the process is put to sleep until SIGCHLD gets
> raised. */
>
> sigsuspend( &new_set )
>
> /* To clean up after all this we finally set the signal mask back to
> what it was before all these manipulations */
>
> sigprocmask( SIG_SETMASK, &old_set, NULL );
I have tried the code.
I don't understand for what kind of tasks should I use that code - can you
give me an example of a task (in words), please.
Also, If I do all of above just before wait,
program don't response forever after sigsuspend command,
even without the above new code, the program isn't being hangged forever,
and does wait till the child ends.
> Of course, you will have to install a signal handler for SIGCHLD
> since by default the signal disposition for SIGCHLD is SIG_IGN,
> but you don't want to ignore it here and in that case you need
> a signal handler.
What do you mean about signal handler ? What exactly should I do ?
Thanks 
| |
| Jens Thoms Toerring 2007-04-18, 7:18 pm |
| Mr. X. <no_spam_please@nospam_please.com> wrote:
[vbcol=seagreen]
> ... someone told me it should be the opposite :
> sigfillset(&new_set);
> sigdlset(&new_set);
> sigprocmask( SIG_BLOCK, &new_set, &old_set );
> Why so ?
According to the documentation I have (e.g. Stevens APUE and the
man pages for sigprocmask()) with SIG_BLOCK "the new signal mask
is the union of the current signal mask and the signal set poin-
ted to by 'new_set'. That is, 'new_set' contains the additional
signals that we want to block." (taken directly from Stevens book,
page 293, with a bit of changes to adapt it to our situatuon). So,
according to that if you want to block SIGCHILD in addition to the
signals already blocked you need to set SIGCHLD in 'new_set' and
nothing else and not do it the other way round.
[vbcol=seagreen]
> I have tried the code.
> I don't understand for what kind of tasks should I use that code - can you
> give me an example of a task (in words), please.
I don't know any real life situation to use something like that (at
least I have never used siguspend() in a program as far as I remem-
ber), it was you that asked for some example code of blocking a sig-
nal and then later use sigsuspend() to wait for the signal blocked
in the meantime.
> Also, If I do all of above just before wait,
> program don't response forever after sigsuspend command,
> even without the above new code, the program isn't being hangged forever,
> and does wait till the child ends.
Sorry, but that sentence doesn't make too much sense to me, perhaps
my English isn't good enough. I guess you should post the code you
are using plus an explanation of what exactly you expect it to do.
[vbcol=seagreen]
> What do you mean about signal handler ? What exactly should I do ?
A signal handler is a function that automatically gets invoked
when the signal it was installed for arrives. You install a
signal handler by a call of sigaction() (preferable to a call
of signal()). And you definitely should learn about signal
handlers and how to install them _before_ you go into the datails
of things like blocking signals or functions like sigsuspend().
I can only recommend that you get a good book about these things
like for example W. Richard Stevens "Advanced programming in the
UNIX Environment" (APUE for short) and read at least chapter 10
carefully. This whole topic is a bit too involved to explain it
with all the necessary details in a few postings in a newsgroup.
Or, since you told that this is part of some homework, you should
consult your lecture notes or maybe even ask your teacher/tutor.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
| |
| Mr. X. 2007-04-19, 1:21 pm |
| O.K.
I have the book of Stevens.
Chapter 10 demonstrates signals,
but I should not use the sigaction (It's the demand on my homework).
It is good book, but it's difficult to understand everything, with no much
samples
(for running processes on background).
One thing,
that I didn't how sig commands help me programming processes,
that runs on background, and not on foreground
(What I have understood : foreground - waits till the child-process totaly
ends,
background - I can run other commands, before the previous command ends),
and since my example doesn't work (I just did simmiliar to yours example :
My code runs on the parent process, after doing pipe + fork), I cannot
understand about signals.
I am looking for some good source code, which explains the above,
and since I didn't find any around the Internet,
I am looking for some help, for good sample code, please.
Thanks 
| |
| Jens Thoms Toerring 2007-04-20, 7:19 am |
| Mr. X. <no_spam_please@nospam_please.com> wrote:
> I have the book of Stevens.
> Chapter 10 demonstrates signals,
> but I should not use the sigaction (It's the demand on my homework).
Well, then there's still the signal() function, but which has it's
drawbacks. And there are several examples in that chapter of how
to install a signal handler using signal().
> It is good book, but it's difficult to understand everything, with no much
> samples
> (for running processes on background).
What got running a process in the background to do with signals
(other than SIGCHLD for which you should install a signal handler
and where you typically just call wait() to reap zombies)?
> One thing,
> that I didn't how sig commands help me programming processes,
> that runs on background, and not on foreground
Me neither, especially since you never specify clearly what exactly
you want to do. What makes you think that signals will help you at
all?
If you're trying to write a program that works similar to a very
simple shell and you want to run a process in the background on
user input like
some_program &
then all you need to do is
a) install a signal handler for SIGCHLD that just calls wait()
when invoked
b) call fork
c) in the child process just exec() 'some_program'
d) in the parent continue to wait for further user input.
If you want something more complicated like
cmd1 | cmd2 &
then one way one it probably can be done is
a) install a signal handler for SIGCHLD that just calls wait()
when invoked
b) call fork
c) in the child process
1) create a pipe
2) call fork
3) in the grandchild do
I) dup2() stdin to the read end of the pipe and close
the other end
II) call exec() for cmd2 (call _exit() if exec() fails)
4) in the child dup2() stdout to the write end of the pipe
and close the other end
5) call exec() for cmd1 (call _exit() if exec() fails)
d) in the parent continue to wait for further user input
> (What I have understood : foreground - waits till the child-process totaly
> ends,
> background - I can run other commands, before the previous command ends),
> and since my example doesn't work (I just did simmiliar to yours example :
> My code runs on the parent process, after doing pipe + fork), I cannot
> understand about signals.
Then show your code, perhaps someone can tell you why it doesn't
work. But if you don't show what you have, how do you expect help?
I am not a clairvoyant and I guess most of the others reading this
also aren't.
> I am looking for some good source code, which explains the above,
Code never explains anything, it just demonstrates how to apply
some methods, which you have to understand first. And for figuring
out which methods to use you have to get a clear picture of the
problem you're trying to solve.
> and since I didn't find any around the Internet,
> I am looking for some help, for good sample code, please.
Sample code for what exactly? You neither explain clearly what
you want to do and you don't even show the code you have, from
which one might perhaps be able to guess what this is all about
and then tell you where you're running into trouble.
But if you want a complete example of a simple shell see for
example Marc Rochkind's "Advanced UNIX Programming", chap. 6.
But I doubt that it's going to be easier to understand then
the examples from Stevens APUE.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
| |
| Mr. X. 2007-04-20, 1:24 pm |
| Thanks ...
As you have said :
> If you're trying to write a program that works similar to a very
> simple shell and you want to run a process in the background on
> user input like
>
> some_program &
>
> then all you need to do is
>
> a) install a signal handler for SIGCHLD that just calls wait()
> when invoked
> b) call fork
> c) in the child process just exec() 'some_program'
> d) in the parent continue to wait for further user input.
>
> If you want something more complicated like
>
> cmd1 | cmd2 &
>
> then one way one it probably can be done is
>
> a) install a signal handler for SIGCHLD that just calls wait()
> when invoked
> b) call fork
> c) in the child process
> 1) create a pipe
> 2) call fork
> 3) in the grandchild do
> I) dup2() stdin to the read end of the pipe and close
> the other end
> II) call exec() for cmd2 (call _exit() if exec() fails)
> 4) in the child dup2() stdout to the write end of the pipe
> and close the other end
> 5) call exec() for cmd1 (call _exit() if exec() fails)
> d) in the parent continue to wait for further user input
>
I want to simmulate the
some_program &
also
cmd1 | cmd2 &
my program did :
> a) install a signal handler for SIGCHLD that just calls wait()
> when invoked
I didn't understand much why.
Also :
my program can simmulation normal shell (without the &).
Here are my steps :
-----------------------
1. I did the all steps, as you have mentioned.
2. just before doing pipe command,
I did :
sigfillset(&newmask);
sigdelset(&newmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
fprintf(stderr,"SIG_BLOCK error");
in order to get only sigchld signal.
What should I do next ?
sigempyset(&zeromask);
if sigsuspend(&zeromask) ... hang my program.
(I just want to simmulate foreground commands, with no "&",
and sigsuspend should be at my code).
3. At the function sgc, as : signal(SIGCHLD, sgc) ...
I did wait(&status) ...
4. I suppose that when using the attitude by waiting on signal procedure
(sgc of step 3 of mine),
It should be for all sub-sub processes.
but, if I do something like execvp, which I need to allocate dynamically
memory,
and free it only after the execvp, so I should do wait on the parent (the
parent shouldn't free the memory, unless the child runs) - isn't this so ?
What is the prefered thing to do on that case ?
5. Is sgc (of step 3) a synchronized function (no 2 processes can run the
sgc) ?
I ask this, because I want to use some global variable on that function.
Thanks 
| |
| Jens Thoms Toerring 2007-04-20, 1:24 pm |
| Mr. X. <no_spam_please@nospam_please.com> wrote:
> Thanks ...
> As you have said :
[vbcol=seagreen]
> I want to simmulate the
> some_program &
> also
> cmd1 | cmd2 &
> my program did :
> I didn't understand much why.
To be able to deal with the SIGCHLD signal send when the child
process dies. Otherwise you end up with a zombie.
> Also :
> my program can simmulation normal shell (without the &).
> Here are my steps :
> -----------------------
> 1. I did the all steps, as you have mentioned.
> 2. just before doing pipe command,
> I did :
> sigfillset(&newmask);
> sigdelset(&newmask, SIGCHLD);
> if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
> fprintf(stderr,"SIG_BLOCK error");
> in order to get only sigchld signal.
Yes, this blocks all signals except SIGCHLD - but only unless
SIGCHLD was already blocked, then it will remain blocked.
> What should I do next ?
> sigempyset(&zeromask);
> if sigsuspend(&zeromask) ... hang my program.
Here you unblock all signals. But since you hadn't SIGCHLD blocked
before and it perhaps already came in before you call sigsuspend()
your program has a chance of hanging here if no other signal get
raised. But how should I know for sure when you always only show
small parts of your program?
> (I just want to simmulate foreground commands, with no "&",
> and sigsuspend should be at my code).
But why when just wait() will do perfectly well and you don't even
have to deal with signals in that case? But if you insist on using
sigsuspend() then block SIGCHLD before calling fork() and call
sigsuspend() with SIGCHLD unblocked afterwards. Every other way
you have a good chance of missing the signal.
> 3. At the function sgc, as : signal(SIGCHLD, sgc) ...
> I did wait(&status) ...
What is tha supposed to mean?
> 4. I suppose that when using the attitude by waiting on signal procedure
> (sgc of step 3 of mine),
What is "waiting on signal procedure"?
> It should be for all sub-sub processes.
What means "should be for all sub-sub processes"? And what is "it"?
> but, if I do something like execvp, which I need to allocate dynamically
> memory,
> and free it only after the execvp, so I should do wait on the parent (the
> parent shouldn't free the memory, unless the child runs) - isn't this so ?
> What is the prefered thing to do on that case ?
Huh? If the call of execvp() was succesful it never returns. So there's
nothing you could do "after" the execvp() call (except the case that the
call failed).
> 5. Is sgc (of step 3) a synchronized function (no 2 processes can run the
> sgc) ?
> I ask this, because I want to use some global variable on that function.
What is a "synchronized function"? And why should it not be called
in 2 processes at the same time? Different processes have a completely
different address space and a global variable in process A has abso-
lutely nothing to do with the same global variable in process B. If
you need to share information between processes you need some commu-
nication channel between them. Proceses aren't threads that share a
common memory space.
Sorry, I give up. Most of the time I have no idea what you're talking
about, you're changing topics constantly and you don't even show the
code you have so far even though I told you several times that that's
what's needed at least.
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
|
|
|