1

I'm writing a code forking (number of 3, 5, ... indefinite number). I wish my program to end after the time specified(parent kills firstly its children then itself probably by calling _exit which is also sig-safe). I mean in signal handler I kill whole children by kill() then call waitpid() for all since both are kind of async-signal-safe function. To do that, I'm using setitimer(ITIMER_REAL, &timer, NULL before forking.

So is it inherited by the forked children?

If it is not inherited, could you show a source?

If it is inherited, do all children end as well after the time is taken? In addition, actually I don't want the case.

concurrencyboy
  • 351
  • 1
  • 11
  • @JonathanLeffler sir, after the time is elapsed completely, main process(parent) kills its children by calling SIGKILL since they serve(accepts request) as far as they are alive. After sending SIGKILL to all of them by a loop, the parent runs again another loop to wait them actually to clean process table resources etc. – concurrencyboy Apr 18 '19 at 21:28
  • I suspect you mean 'calling `kill()` with SIGKILL' rather than 'calling SIGKILL' because SIGKILL is not a function that can be called. Be cautious about using SIGKILL; it prevents a process from executing any cleanup code. It might be sensible to think in terms of sending SIGHUP or SIGTERM to the child processes, then waiting for them to clean up, only sending SIGKILL to any recalcitrant children who don't die quickly enough. – Jonathan Leffler Apr 18 '19 at 22:57
  • @JonathanLeffler firstly, I mean calling kill() with SIGKILL. Do you mean by calling SIGHUP or SIGTERM rather than SIGKILL that I should handle one of the signals you mention so that I can do cleanup if I allocated some place with malloc for example. So could you expand what you mean by saying also SIGKILL to any recalcitrant children who don't die quickly enough? – concurrencyboy Apr 19 '19 at 12:02
  • @JonathanLeffler also by saying cleanup do you mean closing file descriptors? Or more things should be done? If so what things I should do? – concurrencyboy Apr 19 '19 at 12:03

1 Answers1

1

Not inherited.

The POSIX spec for fork explicitly mentions that timers are not inherited and that XSI (timer_create/timer_settime) timers are reset:

  • [XSI] [Option Start] Interval timers shall be reset in the child process. [Option End]
  • Per-process timers created by the parent shall not be inherited by the child process.

A test program like:

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>

void h(int Sig)
{
    char pid[20];
    sprintf(pid,"%d\n",(int)getpid());
    (void)write(1,pid,strlen(pid));
}
int main()
{
    if(0>sigaction(SIGALRM,&(struct sigaction){.sa_handler=h},0)) return perror("sigaction"),1;
    if(0>setitimer(ITIMER_REAL, &(struct itimerval){.it_value.tv_sec=1},0)) return perror("setitimer"),1;
    pid_t ch; if(0>(ch=fork())) return perror("fork"),1;
    pause();
    if(ch){
        sleep(1);
        kill(ch,SIGTERM);
    }
    _exit(0);
}

shows the handler runs only in the parent—it prints only one pid.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • 1
    Thanks for your answer firstly. IIRC, printf variant functions are not asnyc-sig-safe. Do you know any alternative way to print safely PID in signal handler? – concurrencyboy Apr 18 '19 at 13:25
  • 1
    @concurrencyboy Yeah, but `sprintf` is _usually_ AS-safe so I used that in good faith instead of `printf`. You can always roll out your own AS-safe number-to-string function and `write()` the result. – Petr Skocik Apr 18 '19 at 13:32
  • I think better to use sig_atomic_t type flag then polling through it where necessary. – concurrencyboy Apr 18 '19 at 14:57
  • Additionally, do I need to open new question the following question? with pipe, read write block as you know if O_NONBLOCK is not set. How can I make setitimer to do continue its counting? It doesn't continue on blocking. Without any additional thread/process can it be accomplished? – concurrencyboy Apr 18 '19 at 15:12
  • 1
    @concurrencyboy Timers absolutely do continue to run even if your thread/process is blocked. Unless your blocking (`sigprocmask`) the or ignoring the signal, its handler will run, typically interrupting the blocking call (resulting in either an EINTR error or a partial read/write count). – Petr Skocik Apr 18 '19 at 15:27