2

I am writing a C program in which the parent forks n child processes. A child process once created invokes a SIGSTOP to allow other child processes to be created. The parent after creating all the n child processes sends a SIGCONT signal to all the child.

All the child processes execute an infinite loop and share a common resource using semaphores. Now I want that whenever the user presses ctrl-c, the parent and all the child processes terminate together. However before terminating the child processes should update in a file how many times each has used the resource.

eg:

Process 1 - 5 times
Process 2 - 3 times

and so on.

Need help in this implementation please...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ritz
  • 69
  • 7
  • 3
    What have you got? Which parts do you need help with? You will need a signal handler for SIGINT (but probably not for SIGCONT). You should therefore look at `sigaction()`. I assume you have the semaphore code already working? – Jonathan Leffler Jan 13 '12 at 18:23
  • Duplicate? http://stackoverflow.com/questions/284325/how-to-make-child-process-die-after-parent-exits contains a good answer. – ugoren Jan 13 '12 at 19:34
  • 1
    @JonathanLeffler The semaphore part is working fine for me. What I am stuck at is in the portion where, on pressing ctrl-c to exit the child processes should first update in a file how many times each has used the resource. thereafter the child and parent terminate one after the other. – ritz Jan 13 '12 at 19:54
  • 1
    I have tried someting like this...but dont know if it is correct. I have used signal(SIGINT, handler) to handle the SIGINT in the parent and thereafter sending kill(0,SIGQUIT) as part of the handler function to the entire process group. However the issue of writing to a file still needs to be resolved – ritz Jan 13 '12 at 19:59
  • @ritz - Post what you have working already. – ProfessionalAmateur Jan 13 '12 at 20:29

2 Answers2

2

The formal signal handler function should do as little as feasible. The C standard says it can write to a volatile sig_atomic_t variable, or call abort() or _Exit() (or, with restrictions, signal()). POSIX allows more to happen, and you're probably working on Linux (though you didn't say so). So, your signal handler will change the value of a sig_atomic_t variable from 0 to 1 to indicate that the signal occurred.

So, your child processes will be looping. As part of the loop condition, you should check a sig_atomic_t variable to see whether the child should terminate. When it detects that a signal occurred, it will stop looping, open the log file for append, write its information to that file, and exit. You could check the sig_atomic_t variable at other points in the processing than just the main loop condition; that's your decision.

Note that you should use sigaction() rather than signal() to control the signal handling, and you should block interrupts while processing a signal.

So, to summarize:

  • Your signal handler does as little as possible.
  • Your code detects in the main loop when the signal handler has been called and arranges to exit.
  • Your code can also detect when the signal handler has been called at other convenient points.
  • You can call a function to do the logging and exit.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

In order to write the file, you need to add the code to write to said file in your signal handler for SIGINT. If you want each process to write to that file, you're going to need to make sure that the SIGINT gets sent to the entire process group.

You can probably get by without sending the SIGQUIT to each, as you could have each process simply exit itself after processing SIGINT. If you want to optimize a little, you could keep a shared data structure of which processes have already received the SIGINT so that you don't send each process several SIGINTs.

dbeer
  • 6,963
  • 3
  • 31
  • 47