about signals - Unix

This is a discussion on about signals - Unix ; Hello, I want to do something like the following : while (true) { if ( (pid = fork()) perror("fork error\n"); exit(1); } if (pid > 0) { /* parent */ ... } else { ... } .... } ..... If ...

+ Reply to Thread
Results 1 to 10 of 10

Thread: about signals

  1. about signals

    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



  2. Re: about signals

    Mr. X. 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

  3. Re: about signals

    > 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



  4. Re: about signals

    Mr. X. wrote:
    > > 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().


    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

  5. Re: about signals

    > 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



  6. Re: about signals

    Mr. X. wrote:
    > > 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 ?


    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.

    > > /* 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.


    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.

    > > 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 ?


    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

  7. Re: about signals

    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



  8. Re: about signals

    Mr. X. 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

  9. Re: about signals

    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



  10. Re: about signals

    Mr. X. wrote:
    > 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.


    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

+ Reply to Thread