How to signal from parent process to the child? - c

How can i send signal from parent process to the child?
After i write to the pipe i want to send signal to the child process.
pid_t pid;
int filds[2];
pipe(filds);
char *args[150] = {"./draw.out", NULL};
char buff = '\0';
if ((pid = fork()) < 0) { // fork a child process/
printf("*** ERROR: forking child process failed\n");
exit(1);
} else if (pid == 0) {
execvp(args[0], args); // execute the command
} else { // for the parent
char btnPressed = getch();
while (btnPressed != 'q'){
btnPressed = getch();
write(filds[1],buff, BUFF_SIZE);
//signal
}
// signal finish game.
}

kill(PID, SIGwhatever);
however this is probably a poor choice; the better solution is
close(filds[1]);
and handle close of input in the child. I think you're missing a
dup2(files[0],0);
in the child path as well.

Related

How do you read from pipe with both children in C?

int main()
{
int pipefd[2];
char buf;
int pid, pid1;
pid = fork();
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if(pid == 0){ // CHILD 1
close(pipefd[1]);
while(read(pipefd[0],&buf,1) > 0){ // THIS DOESNT WORK
printf("FIRST CHILD WRITES: %s\n",&buf); // THIS DOESNT WORK
} // THIS DOESNT WORK
close(pipefd[0]);
_exit(EXIT_SUCCESS);
}else{
pid1 = fork();
if(pid1 == 0){ // CHILD 2
close(pipefd[1]);
// while(read(pipefd[0],&buf,1) > 0){ // ONLY THIS (WOULD) WORK
// printf("SECOND CHILD WRITES: %s\n",&buf); // ONLY THIS (WOULD) WORK
// } // ONLY THIS (WOULD) WORK
close(pipefd[0]);
_exit(EXIT_SUCCESS);
}else{ // PARENT
close(pipefd[0]);
char* s = "Write To Pipe";
write(pipefd[1],s,strlen(s));
close(pipefd[1]);
wait(NULL); // WAIT FOR CHILD TO TERMINATE
wait(NULL); // WAIT FOR CHILD TO TERMINATE
}
}
return 0;
}
Whenever I try to run the program only the 2ND CHILD can read from the pipe, the 1ST CHILD never. So I tried commenting the second child's pipe reading, however the first child still can't read from the pipe to which the parent wrote into.
Why can't the 1ST CHILD read from the pipe?
Thanks for the help!
The order is wrong. Your code is
pid = fork();
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
You need to create the pipe before you fork. You would probably catch this type of error if you check for errors on the close and/or the read.

How could I know if all processes have been already created before sending signals?

I'm writing a Unix program where the parent process has to send signals to children and a grandson. How could I know if all processes have been already created before sending signals? Because sometimes they don't exist yet. Thanks a lot!
void t(int sig)
{
kill(SIGKILL, pidc1);
kill(SIGKILL, pidc2);
kill(SIGKILL, pidg2);
kill(SIGKILL, pidc3);
}
void handler()
{
write(1, "Signal SIGUSR1\n", 15);
}
pid_t pidc1, pidc2, pidc3, pidg2;
int main(int argc, char **argv)
{
struct sigaction action;
int status;
action.sa_flags = 0;
action.sa_handler = handler;
sigaction(SIGUSR1, &action, NULL);
pidc1 = fork();
if(pidc1 == 0)
{
printf("Child 1\n");
}
pidc2 = fork();
if(pidc2 == 0)
{
printf("Child 2\n");
pidg2 = fork();
if(pidg2 == 0)
{
printf("Grandson 2\n");
}
wait(&status);
}
pidc3 = fork();
if(pidc3 == 0)
{
printf("Child 3\n");
}
kill(pidg2, SIGUSR1);
kill(pidc3, SIGUSR1);
signal(SIGALRM, t);
alarm(10);
wait(&status);
}
Preliminary note: The child code parts in your example program fall through to their parent's code, which is certainly not intended; I'll assume something like return sleep(5); at the end of each block. Also note that the printf()s may malfunction with fork()s and buffered output.
Barmar wrote:
If you need to wait for the grandchild processes to be created, you need some kind of communication from the child to the parent, so it can send the grandchild's PID. Shared memory and a mutex would be a way to do this.
That's absolutely correct. (The direct children are no problem, since the parent knows their PIDs.) Another way to communicate the grandchild's PID is a pipe; your example main() could become:
int main(int argc, char **argv)
{
int status;
sigaction(SIGUSR1, &(struct sigaction){.sa_handler = handler}, NULL);
setbuf(stdout, NULL); // printf() may malfunction without this
pidc1 = fork();
if (pidc1 == 0)
{
printf("Child 1\n"); return sleep(5);
}
int pipefd[2];
pipe(pipefd); // for communicating the grandson's PID
pidc2 = fork();
if (pidc2 == 0)
{
printf("Child 2\n");
pidg2 = fork();
if (pidg2 == 0)
{
printf("Grandson 2\n"); return sleep(5);
}
write(pipefd[1], &pidg2, sizeof pidg2); // write pidg2 to write end
wait(&status); return sleep(5);
}
pidc3 = fork();
if(pidc3 == 0)
{
printf("Child 3\n"); return sleep(5);
}
read(pipefd[0], &pidg2, sizeof pidg2); // read pidg2 from pipe's read end
kill(pidg2, SIGUSR1);
kill(pidc3, SIGUSR1);
}

C save forked pid

Hello i have such problem
pid_t pid1;
pid_t pid2;
void switch_files(int sig_type)
{
printf("%d %d\n", pid1, pid2);
}
int main(int argc, char **argv)
{
pid_t lpid1,lpid2;
if ((lpid1 = fork()) == 0)
{
signal(SIGUSR1, switch_files);
//Some work
} else {
pid1 = lpid1;
}
if ((lpid2 = fork()) == 0)
{
signal(SIGUSR2, switch_files);
//Some work
} else {
pid2 = lpid2;
}
while(scanf("%s", input) > 0)
{
write(pipe1[1], input, strlen(input) + 1);
kill(pid1, SIGUSR1);
}
waitpid(pid1, 0, 0);
waitpid(pid2, 0, 0);
}
So i need to have value of pid1 and pid2 in my callback for signals, and at printf i have 0 0 but in main i have normal value of pids. How i can fix this, thank you for any help.
If you want the child to have the pid, simply ask for it:
if ((lpid1 = fork()) == 0)
{
pid1 = getpid();
pid2 = -1; // other child doesn't even exist yet
signal(SIGUSR1, switch_files);
//Some work
exit(0); // you don't want the child to go executing parent code, do you?
}
And
if ((lpid2 = fork()) == 0)
{
//pid1 already set with pid of 1st child
pid2 = getpid();
signal(SIGUSR2, switch_files);
//Some work
exit(0); // you don't want the child to go executing parent code, do you?
}
If you need to the 1st child to have the pid of the 2nd child, then you need to use some form of IPC, so you can communicate to the the 1st child after also 2nd child has been started and its pid is known.
If you want the children to have information, you have to communicate that information to them somehow. You can use a file, a pipe, shared memory, or any mechanism you want. But you have to pass the information somehow.

2 child process does not display a message

I am trying to learn programming on and I don’t understand why I can't get child 2 to print hello. I have also closed both read and write ends of the pipe for the parent because I don’t want the parent to communicate. Any help is much appreciated.
int main ()
{
int fd[2];
pid_t child_pid, child_pid1;
if (pipe(fd) < 0)
{
printf("Pipe error");
}
child_pid = fork (); // child 1
if (child_pid != 0)
{
printf("im child 1");
dup2 (fd[1], STDIN_FILENO);
printf("greetings");
child_pid1 = fork (); //child 2
if (child_pid1 != 0)
{
printf("im child 2");
dup2(fd[0], STDOUT_FILENO);
printf("hello");
}
else if (child_pid1 > 0) //Parent Code
{
close (fd[0]);
close (fd[1]);
}
}
return 0;
}
Your first if clause is wrong.
child_pid = fork (); // child 1
if (child_pid != 0)
{
printf("im child 1");
}
This is not the child but the parent. If it is the child, then pid will be 0, only on the parent you have child_pid != 0.
The same happens in the second if clause as well.
You should do if(child_pid == 0) in both cases, if you want that code to be executed in the child process.

How to pass signals to child process

Title may be a little confusing, so let me explain. I am trying to write a simple shell to practice my programming. I have got the get a command, fork, exec loop working. However, when I press CTRL-C while child process is still executing, my shell terminates, instead of child process (but child process would keep running). Here is the main function:
int main()
{
dynarray *args; /* pointer to a dynamic array */
int bytes_read;
size_t nbytes = 0;
char *command;
pid_t pid;
printf("Enter command: ");
while ((bytes_read = getline(&command, &nbytes, stdin)) != -1) {
if (bytes_read == -1) {
perror("getline");
exit(EXIT_FAILURE);
}
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid == 0) { /* child process */
args = newdynarray();
char *arg = strtok(command, " \n");
while (arg != NULL) {
addstring(args, arg);
arg = strtok(NULL, " \n");
}
if (args->nval == 0) {
freedynarray(args);
continue;
}
addstring(args, NULL);
char *fullpath = find_executable(args->strings[0]);
if (fullpath == NULL) {
fprintf(stderr, "Couldn't find executable: %s\n", command);
exit(EXIT_FAILURE);
}
if (execv(fullpath, args->strings) == -1) {
perror("execv");
exit(EXIT_FAILURE);
}
} else {
int status;
waitpid(pid, &status, 0);
}
printf("Enter command: ");
}
return 0;
}
I didn't include other parts, because I don't think they are relevant. How can I make my child process catch all the input from stdin until it terminates?
You can register a signal handler for SIGINT in your parent process, and therein use kill(2) to send a signal to the child process, whose PID you should store somewhere.
How can I make my child process catch all the input from stdin until it terminates? Signals generated from stdin keys (such as control C) will be sent to the last process to use stdin, so there's nothing you can do unless you can force your child to use the path.
Instead, you need to create a signal handler in your shell process to catch SIGINT (and others), and resend the signal (using the kill() function) to the process you want to receive it.

Resources