I wrote a code that creates a child with a fork(). The parent of this child should sent a SIGUSR1/2 to its CHILD and the child should answer with a SIGUSR2/1.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void HDL_PSIGUSR(int sig) {
printf("Signal 0x%x received.\n\n", sig);
fflush(stdout);
}
void HDL_SSIGUSR(int sig) {
if (sig == SIGUSR1) {
printf("PID %d -> PID %d: 0x%x\n", getpid(), getppid(), SIGUSR2);
kill(getppid(), SIGUSR2);
} else if (sig == SIGUSR2) {
printf("PID %d -> PID %d: 0x%x\n", getpid(), getppid(), SIGUSR1);
kill(getppid(), SIGUSR1);
}
fflush(stdout);
}
void HDL_SSIGINT(int sig) {
kill(getppid(), SIGINT);
}
void son() {
signal(SIGUSR1, HDL_SSIGUSR);
signal(SIGUSR2, HDL_SSIGUSR);
signal(SIGINT, HDL_SSIGINT);
signal(SIGALRM, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
while (true) {
pause();
}
}
int main() {
int* _buf, n, i, t, timer = 0;
pid_t pid;
char buff[1000];
printf("Number of signals to send: ");
scanf("%d", &n);
printf("Interval time: ");
scanf("%d", &t);
printf("Signals to send: ");
_buf = malloc(n * sizeof *_buf);
for (i = 0; i < n; i++) {
scanf("%d", &_buf[i]);
}
fflush(stdout);
if (pid = fork()) {
signal(SIGUSR1, HDL_PSIGUSR);
signal(SIGUSR2, HDL_PSIGUSR);
i = 0;
while (true) {
i %= n;
//sprintf(buff, "kill -USR1 %d", pid);
//system(buff);
kill(pid, SIGUSR1);
sleep(t);
}
} else {
son();
exit(0);
}
waitpid(pid, (int*)0, 0);
return 0;
}
The problem is that if I use the kill() system call, the child process become a zombie process. Instead, if I use the system() system call and calling from there the command kill on CHILD PID, it works! Why?
Thank you guys! The problem was as said by #Jonathan Leffler and #Shawn. It can be solved with a sleep(1); in the parent process before starting to send signals. I modified my code as shown here:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
bool startProg = false;
void HDL_PSIGUSR(int sig) {
if (!startProg) {
startProg = true;
return;
}
printf("Received signal 0x%x\n", sig);
fflush(stdout);
}
void HDL_SSIGUSR(int sig) {
kill(getppid(), (sig == SIGUSR1) ? SIGUSR2 : SIGUSR1);
}
void HDL_SSIGINT(int sig) {
kill(getppid(), SIGINT);
}
void son() {
signal(SIGUSR1, HDL_SSIGUSR);
signal(SIGUSR2, HDL_SSIGUSR);
signal(SIGINT, HDL_SSIGINT);
signal(SIGALRM, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
kill(getppid(), SIGUSR1);
while (true) {
pause();
}
}
int main() {
int* _buf, n, i, t;
pid_t pid;
printf("Number of signals to send: ");
scanf("%d", &n);
printf("Interval time: ");
scanf("%d", &t);
printf("Signals to send: ");
_buf = malloc(n * sizeof *_buf);
for (i = 0; i < n; i++) {
scanf("%d", &_buf[i]);
}
fflush(stdout);
if (pid = fork()) {
signal(SIGUSR1, HDL_PSIGUSR);
signal(SIGUSR2, HDL_PSIGUSR);
while (!startProg) {
pause();
}
i = 0;
while (true) {
i %= n;
kill(pid, _buf[i++]);
pause();
sleep(t);
}
} else {
son();
exit(0);
}
waitpid(pid, (int*)0, 0);
return 0;
}
Related
I have to create a program that generates 2 childs and each of them has to generate a random number. After that the child who generated the lowest number has to send a SIGUSR1 to the other child. In my case i wanna send a SIGCONT to child 1 to wake him up so that he can send SIGUSR1 to the other process but child 1 doesn't wake up.. any help? Thanks in advance.
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define N 2
int getRand(int upper)
{
srand(time(0));
int random;
random = rand() % upper;
return random;
}
void sighandler(int signo)
{
if (signo == SIGUSR1)
{
printf("Received SIGUSR1, my PID is %d\n\n", getpid());
exit(0);
}
if (signo == SIGUSR2)
{
printf("Received SIGUSR2.. I woke up! (My PID is %d)\n\n", getpid());
}
}
int main (int argc, char **argv)
{
int i, r, m, b;
int status = 0;
int tabcpid[N], ppid, wpid;
int fd[2], fdbool[2]; //fd [0 = read] [1 = write]
sigset_t set, zeromask;
struct sigaction action;
//Gestione segnali
sigemptyset(&zeromask);
sigemptyset(&action.sa_mask);
action.sa_handler = sighandler;
action.sa_flags = 0;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
if (sigaction(SIGUSR1, &action, NULL) == -1)
{
perror("Error while doing sigaction.\n\n");
}
if (pipe(fd) == -1)
{
printf("Error opening pipe fd!\n\n");
exit(1);
}
if (pipe(fdbool) == -1)
{
printf("Error opening pipe fdbool!\n\n");
exit(1);
}
printf("\nPipes opened successfully. Forking ...\n\n");
sleep(2);
for (i = 0; i < N; i++)
{
if ((tabcpid[i] = fork()) == 0) //Child code
{
int n = atoi(argv[1]);
m = getRand(n);
b = 20;
ppid = getppid();
printf("I'm the son process #%d with PID: %d\n", i + 1, getpid());
printf("Random number in interval 0 - %d: %d\n\n", n, m);
sleep(2);
if (i == 0)
{
close(fd[0]);
write(fd[1], &m, sizeof(int));
close(fd[1]);
printf("Suspending..\n\n");
sigsuspend(&zeromask);
printf("So' ripartitoo\n\n");
/*
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
printf("--- b value: %d\n\n", b);
if (b == 0)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother.\n\n", getpid());
kill(tabcpid[1], SIGUSR1);
}
sleep(2);
*/
}
else
{
close(fd[1]);
read(fd[0], &r, sizeof(int));
close(fd[0]);
int lower = (r < m) ? r : m;
int igotlower = (m < r) ? 1 : 0;
printf("--- igotlower value: %d\n\n", igotlower);
close(fdbool[0]);
write(fdbool[1], &igotlower, sizeof(int));
close(fdbool[1]);
//printf("Got %d from other child process, while i got %d.\nThe smallest number is %d.\nMy PID is %d and the other process' PID is %d.\n\n", r, m, lower, getpid(), tabcpid[0]);
//sleep(2);
if (igotlower == 1)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother..\n\n", getpid());
kill(tabcpid[0], SIGUSR1);
sigsuspend(&zeromask);
}
else
{
printf("I'm sending SIGCONT to %d\n\n", tabcpid[0]);
kill(tabcpid[0], SIGCONT);
sigsuspend(&zeromask);
}
}
sleep(2);
}
sleep(2);
}
wait(&status);
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
kill(tabcpid[b], SIGUSR1);
wait(&status);
printf("It's me the father... it's all over, we're done!\n\n");
sleep(2);
return 0;
}
I need to create a program, which will create child process that will handle processes. In case of SIGXCPU called, child process should close, but when other signal is received, process shouldn't close, but display information. How could I change signals_handler function to stop closing my process?
I call signals from second terminal window.
void signals_handler(int signal) {
psignal(signal,"\nRecived signal");
printf("Signal number is: %d\n", signal);
return;
}
void sig_XCPU(int signal() {
signal(XCPU, sig_XCPU);
}
...
int main(void)
{
if(fork() == 0) {
print("PID: %d", getpid();
signal(SIGXCPU, sig_xcpu)
for(int = 1; i < 65; i++) {
if(i != 24) //SIGXCPU number
signal(i, signals_handler);
}
sleep(100);
return 0;
}
}
return 0;
}
You can test like this:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_handle(int sig) {
switch (sig) {
case SIGXCPU: {
char st[] = "child recesive SIGXCPU, quit\n";
write(STDOUT_FILENO, st, sizeof(st));
exit(EXIT_SUCCESS);
break;
}
case SIGINT: {
char st[] = "child recesive SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
break;
}
default: break;
}
return;
}
void set_signal() {
signal(SIGXCPU, signal_handle);
signal(SIGINT, signal_handle);
}
int main() {
pid_t pid = fork();
if (pid == 0) { // child
set_signal();
char st[] = "child set signal\n";
write(STDOUT_FILENO, st, sizeof(st));
for (;;)
;
}
// parent
sleep(3); // wait child set_signal
// test SIGINT
{
char st[] = "parent send SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGINT);
}
sleep(3);
// test SIGXCPU
{
char st[] = "parent send SIGXCPU\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGXCPU);
}
wait(NULL);
return 0;
}
I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}
In my following program i have two processes( the father and the child) both do the same thing but we want to figure out how will finish his task first. There is a randomized number of seconds both will sleep causing the challenge of who finishes first more random. Both are sending signals to the other process, when five signals have been recieved the process will then send a SIGTERM to the other process signaling that it has finished first. that other process will print that the opponent process has won. My problem is with sending that sigterm signal to the other process, ive tried kill function, singal function and dont know where is my mistake and what to try next. So any help would e=be appreciated below is my code:
//--------including--------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
//-------global----------------
int sig1_counter=0;
int sig2_counter=0;
//-------prototypes--------------
void catch_sigusr1(int sig_num) ;
void catch_sigusr2(int sig_num) ;
void do_son() ;
void do_dad() ;
//--------main------------------
int main (){
pid_t pid;
srand((unsigned)time(NULL));
signal(SIGUSR1, catch_sigusr1) ;
signal(SIGUSR2, catch_sigusr2) ;
pid = fork() ;
switch(pid) {
case -1 : perror("fork() failed") ;
exit(EXIT_FAILURE) ;
case 0 : do_son() ;
exit(EXIT_SUCCESS) ;
default: do_dad() ;
exit(EXIT_SUCCESS) ;
}
return EXIT_SUCCESS;
}
//-------functions-------------------
void do_son() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void do_dad() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void catch_sigusr1(int sig_num) {
signal(SIGUSR1, catch_sigusr1);
printf(" process %d got signal SIGUSR1\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig1_counter++;
if (sig1_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM); // here we have a mistake
//signal(SIGTERM,catch_sigusr2); // !!!!!!!!!!!
exit(EXIT_SUCCESS);
}
}
//---------------------------------
void catch_sigusr2(int sig_num) {
signal(SIGUSR2, catch_sigusr2) ;
printf(" process %d got signal SIGUSR2\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig2_counter++;
if (sig2_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM);
//signal (SIGTERM,catch_sigusr1);
exit(EXIT_SUCCESS);
}
}
Both your do_son() and do_dad() functions send signals to getpid(), which means they are signalling only themselves rather than each other.
In order to signal each other, you need:
do_dad() to send the signal to pid, the return value from fork() being the child PID; and
do_son() to send the signal to getppid(), the parent PID, noting the use of non-sexist terms in the system call :-)
In other words, something like this in your main function:
switch (pid = fork()) {
case -1:
perror("fork() failed");
break;
case 0:
do_both(getppid());
break;
default:
do_both(pid);
break;
}
The reason there's no distinct parent and child function any more is that the only difference is which PID gets signalled. Because you're passing that in as a parameter, you can combine the two functions:
void do_both(pid_t other) {
for (int i = 0; i < 10; i++) {
int sleep_time = rand() % 4;
sleep(sleep_time);
if ((rand() % 2) == 0)
kill(getpid(), SIGUSR1);
else
kill(getpid(), SIGUSR2);
}
}
Hi I've this problem to solve with a functional program in C.
"Write a C program where a process F create a childprocess C.
The childprocess C waits the user to type the password, if is correct sends a signal SIGUSR1 to the father, if after 3 attempts the password is still incorrect it will send a SIGUSR2 signal to the father and terminate; if it receives from the father SIGUSR1 signal must stop viewing the "timeout" message.
His father after 30 seconds (if it has not received any signal from the child) must send the signal SIGUSR1 to the child and end with exit(1); if it receives the SIGUSR1 signal must end with exit(0); if it receives the signal SIGUSR2 must end with exit (2)."
I'm trying to solve it but I'm stuck. This is what I've done:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
exit(2);
}
}
void childprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[], password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (enteredpassword == password)
signal(SIGUSR1, fatherprocess);
} else {
signal(SIGUSR2, fatherprocess);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
signal(SIGUSR1, childprocess);
}
}
return 0;
}
I've edited my program in this way:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal, int fatherpid){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
kill(fatherpid, SIGUSR1);
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
kill(fatherpid, SIGUSR2);
exit(2);
}
}
void childprocess(int mysignal, int childpid){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
kill(childpid, SIGUSR1);
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[] = "test", password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (strcmp(enteredpassword, password) == 0)
fatherprocess(SIGUSR1, fatherpid);
} else {
fatherprocess(SIGUSR2, fatherpid);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
childprocess(SIGUSR1, childpid);
}
}
return 0;
}
Now it works perfectly but I don't know if I've respected the exercise text.
As was mentioned in the comments (by Jonathan Leffler), you need to use the kill() system call (to send the signals) and register a signal handler using a call like sigaction(). I have linked these two calls to online manual pages that provide additional information about them.
Here's some code that demonstrates how these can be used towards achieving your stated goal. You will still need to add/modify the code for things like the prompts you want and the acceptable input string. Please note that I'm not claiming this to be the best way to do it, only that it's an example of how it could be done (it compiled and worked for me):
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static void get_password(char* buf, int maxbuf)
{
fgets(buf, maxbuf, stdin);
}
static int is_password_correct(char* buf)
{
return buf[0] == 'a';
}
volatile int got_signal = 0;
volatile int child_signal = 0;
static void parent_sig_handler(int signum)
{
if (!got_signal)
{
got_signal = signum;
printf("parent_sig_handler: got sig %d\n", signum);
}
}
static void child_sig_handler(int signum)
{
if (!child_signal)
{
child_signal = signum;
printf("child_sig_handler: got sig %d\n", signum);
}
}
int main()
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_handler = parent_sig_handler;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("error forking");
exit(3);
}
if (child_pid == 0)
{
printf("child running\n");
act.sa_handler = child_sig_handler;
sigaction(SIGUSR1, &act, NULL);
pid_t parent_pid = getppid();
for (int i = 0; i < 3; ++i)
{
char passwd[64];
passwd[0] = '\0';
get_password(passwd, sizeof(passwd));
if (is_password_correct(passwd))
{
kill(parent_pid, SIGUSR1);
exit(0);
}
}
kill(parent_pid, SIGUSR2);
exit(2);
}
printf("parent running\n");
alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */
sigset_t sigmask;
sigemptyset(&sigmask);
while (!got_signal)
{
sigsuspend(&sigmask);
}
switch (got_signal)
{
case SIGALRM:
kill(child_pid, SIGUSR1);
exit(1);
case SIGUSR1:
exit(0);
case SIGUSR2:
exit(2);
default:
exit(3);
}
exit(3);
}