I want to make it so that parent process executes before the child thread does. I'm not sure where I'm going wrong to get the order my program is outputting.
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
}
OUTPUT:
signal has changed
signal has changed
parent has started
parent is done
child has started
child is done
The simplest way to exclude concurrent execution is a lock. Have the "parent" (original thread) take a lock before calling pthread_create, and only unlock it when it's ready for the "child" (new thread) to to run. The "child" should take the lock before doing anything; it can then unlock it immediately if it wants, or keep it to control access to shared state.
Related
Moving straight to the issue, how do I make Ctrl+z do what the title states?
My program implements a parent process which creates a single child process.
Both processes will display the process ID and once the child terminates a signal is sent to the parent process and the parent signal handler will display a text stating a signal has been captured.
On the child process, on top of displaying the child's process ID, it must generate a random number between 10 and 50 every time Ctrl + z is pressed. So far I can only make the child process generate 1 random number.
Below is my code:
void main() {
int pid;
int x;
int fd[2];
const int MAXLINE=4096;
char line[MAXLINE];
pid=fork();
if (pipe(fd) < 0) {
printf("Pipe error!");
}
if (pid < 0) {
printf("Fork error!");
} else if (pid == 0) { //Child process
signal(SIGTSTP, childsignal_handler);
printf("The process id is: %i\n", getpid());
sleep(1000); //Implemented to wait for a signal
} else {
printf("The process id is: %i\n", getpid()); //Parent process
pause(); //Waits for the Child process to finish
}
}
parent signal handler:
void parentsignal_handler(int signo) { //Signal Handler for the parent process
printf("The signal in the parent process has been captured\n");
}
child signal handler:
void childsignal_handler(int signo) { //Signal Handler for the child process
signal(SIGTSTP, childsignal_handler);
printf("\nThe signal in the child process has been captured\n");
randomnumbergenerator();
pause();
}
The random number generator:
void randomnumbergenerator() { //Random number generator to run everytime Ctrl+z is pressed
//signal(SIGTSTP, childsignal_handler);
int number;
int number2 = 10;
printf("Welcome to random number generator!");
printf("\nRandom number generated = %d\n", rand() % 40 + 10);
}
PS: I have read several documentations regarding various solutions such as sigsuspend, sigprocmask,pause and so on but none of them worked so far.
below are some of the documentations i have read so far:
https://www.gnu.org/software/libc/manual/html_node/Waiting-for-a-Signal.html#Waiting-for-a-Signal
https://man7.org/linux/man-pages/man2/pause.2.html
i need to implement a signal that will detect the child terminating
You don't exactly need to implement a signal; you just need to install the handler that you already have:
signal(SIGCLD, parentsignal_handler);
how do I make Ctrl+z do what the title states?
So far I can only make the child process generate 1 random number.
To prevent the parent process from being suspended (and therewith losing signal delivery), ignore the STOP signal in the parent:
signal(SIGTSTP, SIG_IGN);
And you should really pay attention to Ian Abbott's first comment and remove pause() from the signal handler; otherwise after Ctrl-Z was pressed the program will not end. At the same time change sleep(…) to while (sleep(…)) to keep a timed suspension instead of the unlimited pause().
I'm trying to create a program where a process forks, creating a child process, and the parent must always finish printing to the screen before the child is finished printing to the screen, no matter what. I also wish to accomplish this using signals instead of pipelining.
It is a similar problem to the question asked here: Explanation of sigsuspend needed
I understand that kill(pid,signal); is to send a signal to that pid and tell it to finish executing and terminate.
The problem is, when it executes, the child doesn't print after the suspend. Heres the code:
int main(void){
pid_t pid;
int i;
pid = fork();
if(pid==0){
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
sigsuspend(&mask);
printf("The child is now complete \n");
}
else{
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
}
exit(0);
}
}
I have managed to accomplish my task (printing the parent before the child) by using a global variable int x = 0; and a signal handler method void handle1(int s){x = 1;}before the main. In the main I added signal(SIGUSR1,handle1); In the child I removed all the sigset and sigsuspend lines and instead wrote while(x==0){/*do_nothing*/} 1 line before the printf statement. So when the parent executes kill(pid,SIGUSR1) the signal handler which is inherited by the child process also gets executed and sets x=1. So the child now leaves the while loop and can print it's statement.
However I believe it would be helpful to know how to accomplish this task using sigmask_t and sigsuspend() but i cant get it to work that way.
There are 3 problems in your code:
SIGUSR1 is the signal you want to deliver to the child. You can't use sigaddset(&mask,SIGUSR1);, it does exactly the opposite of your intention.
According to POSIX standard sigsuspend() below, you should install a signal handler for SIGUSR1 to make sigsuspend() continue the following code, since the default behavior of SIGUSR1 is termination.
The sigsuspend() function shall replace the current signal mask of the calling thread with the set of signals pointed to by sigmask and then suspend the thread until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process.
It would be better if you collect the child from the parent, otherwise there is a race condition.
The code below will work:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void handler(int sig) {}
int main(void){
pid_t pid;
int i;
pid = fork();
signal(SIGUSR1, handler);
if(pid==0){
sigset_t mask;
sigemptyset(&mask);
//sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
sigsuspend(&mask);
printf("The child is now complete \n");
}
else{
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
}
wait(NULL);
exit(0);
}
}
You have a few issues.
Your parent process should wait for the child to complete. This allows for diagnostics (such as properly waiting for the child to print), but is otherwise a bookkeeping task that is a good habit even when the waiting process will just exit:
printf("This is the parentProcess id = %d \n",getpid());
printf("The parentProcess is complete\n");
sleep(1);
int j = kill(pid,SIGUSR1);
if (j!=0)
{
perror(NULL);
exit(0);
}
waitpid(pid, NULL, 0);
exit(0);
Now, you have set SIGUSR1 in your mask to sigsuspend(), which causes the signal to be ignored. This is now more obvious once the parent is made to wait, because the parent will never exit. So, remove the line of code that sets SIGUSR1.
Finally, the default handler for SIGUSR1 will simply cause the process to exit, and so the printf will not get a chance to print. If you want it to print, you should add a signal handler for SIGUSR1. It doesn't have to do anything.
void h (int s) {}
...
sigset_t mask;
sigemptyset(&mask);
//sigaddset(&mask,SIGUSR1);
printf("This is the child Process id = %d \n",getpid());
struct sigaction sa = { .sa_handler = h };
sigaction(SIGUSR1, &sa, NULL);
sigsuspend(&mask);
printf("The child is now complete \n");
I've written a C program that creates a child thread. After creating the child thread, the parent thread should output two messages. The first being "I am the parent" and the second "The parent is done". The same should occur for the child thread "I am the child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve this in my code below?
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
}
Once a thread created it process independently and act like a separate process from the main thread. In your case you are joining the child thread after the statement printf("The parent is done! \n");. It not necessary that operating system will complete the child thread first always. Hence your expected result might not meet always. put a long sleep statement just before statement printf("The parent is done! \n"); and check but still not necessary that child will complete first.
The reason your code doesn't work is because you aren't making sure that the second printf in the parent thread is being executed before the second printf in the child thread.
A good option in this case would be to use mutexes. In this case, you can use a mutex to act as a 'guard' before the second printf, so the code will look something like this:
pthread_mutex_t print_lock;
...
In print_child:
// can only acquire after the parent releases, therefore guaranteeing that
// the parent thread has already printed the second statement
pthread_mutex_lock(&print_lock);
printf("The child is done! \n ");
pthread_mutex_unlock(&print_lock);
In main:
// lock it before the child thread is
// started, therefore guaranteeing the parent will have initial ownership
pthread_mutex_lock(&print_lock);
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
printf("The parent is done! \n");
pthread_mutex_unlock(&print_lock);
...
Just put following line after printf("The parent has started...\n"); and before printf("The parent is done! \n");:
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
So corrected code will be as following:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
int status = 0;
void *print_child(void *arg)
{
while (status == 0)
{
printf("Signal hasn't changed..\n");
sleep(1);
}
printf("The child has started...\n");
printf("The child is done! \n ");
}
int main()
{
pthread_t child;
pthread_create(&child, NULL, &print_child, NULL);
sleep(2);
printf("The parent has started...\n");
status++;
if (pthread_join(child, NULL))
{
printf("ERROR");
exit(1);
}
printf("The parent is done! \n");
return 0;
}
This is a strange question. I have 2 different program:
server and client.
server start, alloc all the message queue and start to waitin for a signal from client (the signal is for tell to the server that "there are new message").
the server remain in an infinite loop until recive SIGQUIT.
the client, when casted, start to send a huge number of message to the server
for(;;){//infinite loop
wait(sem,1); //wait for new message
rc = msgctl(msgid, IPC_STAT, &qbuff);
seq_num++;
pid=fork(); //new process for take the message
if(!pid){
if((msgrcv(msgid, &q, msgsz, 1,MSG_NOERROR))== -1)
perror("msgrcv error");
else{
pthread_mutex_lock(&mutex); //start critic sector
printf("\nthere is a prenotation\n");
q.price=get_conf_value(q.kindof_service)+(q.priority*get_conf_value(3)); //costo = costo_visita + (priorità * costo_priorità)
q.turn=seq_num-q.priority; //assign turn
pthread_mutex_unlock(&mutex); //end critic sector
if(q.turn<0)q.turn=0; //controllo del turno che non sia minore di 0
printf("---------------------------");
printf("\nPrenotation number %i\npid caller: %i\npriorità: %i\n for %i\ncost %i\nturn %i\n",seq_num,q.clientId,q.priority, q.kindof_service ,q.price, q.turn);
printf("---------------------------\nPrenotation ok\n\n\n");
}
printf("\nsuccess.\n");
exit(1); //close children process
}
}
The problem is that, in this way the father leave so much zombies. If i add
else{//i am the father
waitpid(pid, 0, 0);
}
there is the problem that the primary process fork, then wait until the child is ended, then fork again.
i need that the father fork so many time and that dont wait the end of the process before fork again.
But without the waitpid the problem is another.. because after that he start all the process needed for receive all the message, the father take the control and still waitin for another signal from the client (the first wait(sem,1) ), leaving so much zombie process.
I don't know if I explained it well.. is very difficult in english -_-
So, i want a server that, received the signal, fork many many times. any child take a message and do some stuff, then the child end. Meanwhile the server continue to wait for new incoming message. All without make zombies :)
One way to fire-and-forget processes without having to worry about zombies is to fork twice.
Each process has a parent process. If the parent process exits before the child does, the child is becoming an orphan, and is inherited by init (process 1) - which will wait for all children, preventing them to become zombies without manual work.
So what you can do is to fork, and fork yet again in the child process. Then, you can let the child exit, which will cause the grandchild (where you do your work) to be inherited by init. The parent process can wait for the child (which won't take long, because the child did nothing else than fork and exit). When the grandchild is exiting, init will automatically wait for it.
/* fire and forget */
int execute_detached(char **cmdline)
{
pid_t pid;
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* parent */
waitpid(pid, NULL, 0);
return 1;
}
else { /* child */
if((pid = fork()) < 0) { /* fork error */
perror("fork");
return 0;
}
else if(pid > 0) { /* child */
/* make grand child an orphan */
_exit(0);
}
else { /* grand child */
execvp(cmdline[0], cmdline);
perror("execvp");
_exit(1);
}
}
return 0;
}
What I want to do is create a parent process that lasts for 5 seconds. I also want it to send a SIGUSR1 signal every second. On this signal I want the child to do something.
The code that I put together so far is:
void alarmHandler(int sig) {
printf("\nalarm called\n");
exit(0);
}
void childHandler(int sig) {
printf("child called");
signal(SIGUSR1, childHandler);
}
int main() {
pid_t val;
if((val = fork())) { //parinte
signal(SIGALRM, alarmHandler);
printf("parent");
alarm(5);
while(1) {
kill(val, SIGUSR1);
sleep(1);
}
}else {
signal(SIGUSR1, childHandler);
printf("child");
}
return 0;
}
What I get is:
child
parent
alarm called
What I want:
child
parent
child called
child called
child called
child called
child called
alarm called
Your parent has the while loop. The child does the following:
signal(SIGUSR1, childHandler);
printf("child");
And then exits.
If it does receive SIGUSR before the exit, this will also be executed
printf("child called");
signal(SIGUSR1, childHandler);
Therefore you have a race condition as the number of child called is printed.
Just put a while (1) {} after the printf("child");
Base on the original code, add two blocks:
flush the printf: setbuf(stdout, NULL);
keep the child running: while (1) pause();
The code list as follow:
#include "stdio.h"
#include "stdlib.h"
#include <signal.h>
/* For a real-world program, printing from a signal handler is not very safe.
* A signal handler should do as little as it can, preferably only setting a flag here or there.
* And the flag should be declared `volatile`.
* Real-world example:
* I once worked on a system that used an Access database as a back end,
* and under certain circumstances a printf() call in a signal handler would write to the .mdb file instead of stdout,
* hosing the database beyond repair.
*/
void alarmHandler(int sig)
{
printf("\nparent signal alarm handler: times up\n");
exit(0);
}
void childHandler(int sig)
{
printf("\nchild signal handler\n");
// The old style should install the handler again.
signal(SIGUSR1, childHandler);
}
int main()
{
pid_t val;
signal(SIGALRM, alarmHandler);
// If not set this, we cann't the child's output.
// The stdout stream is buffered, so will only display what's in the buffer after it reaches a newline (or when it's told to).
setbuf(stdout, NULL);
if ((val = fork())) { //parinte
printf("\nparent\n");
// #Note that there is only one alarm clock per process.
// the alarm() function will return a value if another alarm has been previously set.
//
// sets a timer that generates the SIGALARM signal when times up.
// If we ignore or don’t catch this signal, the process is terminated.
alarm(5);
while(1) {
sleep(1);
kill(val, SIGUSR1);
}
printf("\nparent exit\n");
} else {
signal(SIGUSR1, childHandler);
printf("\nchild\n");
while (1)
pause(); // The pause() function suspends the process until a signal is caught.
printf("\nchild exit\n");
}
return 0;
}
And the output:
parent
child
child signal handler
child signal handler
child signal handler
child signal handler
parent signal alarm handler: times up