sending synchronized signal among 3 processes - c

I'm working on signal project get a file with 0, increase to the input (ex ./count 300 sample.txt) by using sync signals p1->p2->p3->p1, after they increase number by 1, the fall in to sleep and call next one.
but I got stuck with two problems
how to and where to implement increasing number process, in signal handling or main( 0 -> 1 -> 2 ... input )
don't know how to implement with sigwait() or sigprocmask() what's the difference? . can i choose either one to guarantee that they are synchronized? or should I just use sleep?
belows are code that I've been working on so far.
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
void sig_usr1(int signo)
{
char a;
sigset_t sigset, oldset;
sigemptyset (&oldset);
sigemptyset (&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, &oldset);
fd =open("./sample.txt",O_RDWR);
pread (fd, a, sizeof(a));
if (argv[0]>a)
{a ++;
truncate ("./sample.txt", 0);
write(fd, a, sizeof(a));
}
}
int main (int argc, char** argv)
{
int fd;
int num=0;
struct sigaction usrsig ;
if(!(argv[0]>0))
printf("insert positive integer");
fd = open("./sample.txt",O_RDWR|O_CREAT|O_TRUNC);
write(fd, num ,sizeof(num);
pid_t child[3];
usrsig.sa_handler =sig_usr; // Parent
sigemptyset(&usrsig.sa_mask);
usrsig1.sa_flags = 0;
sigaction(SIGUSR1,&usrsig, 0);
for ( i=0; i<3; i++)
{
child[i] = fork();
if(child[i] == 0)
break;
}
pid_t prev;
if(i ==0) prev = getppid();
else prev = child[i-1];
kill(pid_prev, SIGUSR1)
}

Related

Creating a process pool C Linux

I have an assignment and I am not quite sure how to go about it. Basically I have to create a coordinator process which creates 5 working processes which are waiting to be awakened. The coordinator passes a marker(integer) to the first process, then that process increments the marker by 1 and passes it to the next process. The coordinator process awakens the next process which does the same and so on. The so called marker should go through all the processes 10 times and in the end its value should be printed by the coordinator. Signals should be used as well as shared memory for the marker.
So I created 5 processes and I am thinking that on every iteration there should be a signal and a handler should be passed which will basically do all the work with the marker.
This is my first time working with processes. This is what I have so far:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <signal.h>
#define numOfProcesses 5
pid_t procIDs[5];
void handler(int signum){
//marker and all work here
}
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}else if(procIDs == 0){
pause();
}
}
}
int main(){
createProcesses();
int i;
for(i = 0; i < numOfProcesses; i++){
pkill(SIGUSR1, handler);
}
return 0;
}
I honestly don't know how to go about this. I would really appreciate a piece of advice. Thanks in advance!
This is what I have come up with. Sorry for answering, I couldn't find out how to format code in a comment. Anyway:
It should be 10 times each process. I am using shared memory so I guess I don't need a global variable for the marker? This is what I have come up with:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/shm.h>
#include<signal.h>
#include<sys/ipc.h>
#define numOfProcesses 5
#define numOfLoops 10
pid_t* procIDs[5];
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}
else if(procIDs == 0){
pause();
}
}
}
void init(){//init marker = 0
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data;
data = (int*) shmat(shID, 0, 0);
*data = 0;
}
int* getValue(){//get value of marker
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data = shmat(shID, 0, 0);
return data;
}
void increment(int sig){//increment + 1
if(sig == SIGUSR1){
int temp;
int* data;
data = getValue();
temp = *data;
temp++;
*data = temp;
}
}
void yourFunc(int count, pid_t* mypid, int mysig){
if(count == 0){
return;
}else{
printf("Signal sent :: to PID : %d\n", mypid);
kill(*mypid, SIGUSR1);
yourFunc(count -1, ++mypid, SIGUSR1);
}
}
int main(){
signal(SIGUSR1, increment);
init();
int i,j;
createProcesses();
for(j = 0; j < numOfLoops; j++){//loop every pid 10 times
pid_t* currProcess = procIDs[0];
yourFunc(numOfProcesses, currProcess, SIGUSR1);
}
int* data = getValue();
printf("Marker: %d\n", *data);
return 0;
}
I tried your problem, but I am really baffled by the structure of your question, its really unclear what your problem statement is.
10 times each(10 times per process or a total of 10 times(2 times per process)
You say the processes are waiting to be awakened, which hints that they are not child processes rather other processes running on the system, and would require a fifo to communicate.
Nevertheless, the following is what I could conclude from the limited information.
You need to create a function which would be invoked 10 times(loop) by the coordinator on the first process(waiting to be awakened)
The function would recursively invoke the second process and so on till the last sleeping process.
You'll have to use SIGUSR1, and define action for it in a custom signal handler,
eg.
signal(SIGUSR1,custom_handler)
You will need to keep marker as a global variable.
Because C is a procedural language and kernel's scheduling is not in your hands once a process terminates you cannot recall it or ensure same PID for a process on forking.
So if you are thinking of creating processes inside functions which will be paused and on getting a signal shall resume, fine.....!, But it would be a one-off.
That's all I can say by the limited information your question presents.
Following is the above idea in C.
Initialise count = 5 (no. of processes)in the caller.
mypid points to the first process's PID.
void party_time(int count, pid_t* mypid, int mysig)
{
if(count == 0)
return;
else
{
printf("Signal sent :: to PID : %d\n",*mypid);
kill(*mypid,SIGUSR1);
party_time(count - 1 ,++mypid,SIGUSR1);
}
}

How to send a signal to a child several times avoiding zombie state? C language

I need to send a signal to a child process 3 times.
The problem is that the child only receives the signal once and then transforms into a zombie.
The expected output would be:
 I'm the child 11385 and i received SIGUSR1
 I'm the child 11385 and i received SIGUSR1
 I'm the child 11385 and i received SIGUSR1
But the real output is:
 I'm the child 11385 and i received SIGUSR1
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void my_handler()
{
printf("\n I'm the child %i and i received SIGUSR1\n", getpid());
}
int main (int argc, char **argv) {
int *array;
int N = 10;
int i;
pid_t pid1;
array=(int*)malloc(sizeof(int)*N);
signal(SIGUSR1,my_handler);
for (i = 0; i< N; i++)
{
pid1 = fork();
if(pid1 < 0)
{
exit(EXIT_FAILURE);
}
else if (pid1 > 0)
{
array[i]= pid1;
}
else
{
sleep(100);
exit(EXIT_SUCCESS);
}
}
i=0;
while(i<3) // I need to call the son 3 times
{
kill(array[1], SIGUSR1);
i++;
}
}
When the child receives the signal, it is probably waiting for the sleep to terminate. The first signal will interrupt the sleep even if the time hasn't expired, causing it to return with errno set to EINTR. If you want it to keep sleeping, you need to call sleep again.
your parent process exited without wait()ing for the child
The signals could be sent to fast, I added a short delay
i added more delays
the correct signature for a signal handler is void handler(int signum) This is crucial, because the handler is called with an argument, and the stack layout is different for signal handlers.
you should not call printf() from a signal handler, it is not async safe.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
char pidstr[10];
char massage[]=" I'm the child and i received SIGUSR1\n";
#define CNT 1
void my_handler(int signum)
{
write(0, massage, strlen(massage));
}
int main (int argc, char **argv) {
int i , err, status;
pid_t pid1;
int array[CNT];
signal(SIGUSR1, my_handler);
for (i = 0; i< CNT; i++) {
pid1 = fork();
if(pid1 < 0) { exit(EXIT_FAILURE); }
else if (pid1 > 0) {
printf("ChildPid=%d\n", pid1 );
array[i]= pid1;
}
else
{ // child
// signal(SIGUSR1, my_handler);
sprintf(pidstr,"[%d]", getpid() );
memcpy (massage,pidstr, strlen(pidstr));
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
exit(EXIT_SUCCESS);
}
}
sleep(10);
for (i=0; i<3; i++) {
err = kill(array[0], SIGUSR1);
printf("Err=%d:%d\n", err, (err) ? errno: 0 );
sleep(1);
}
while ( (pid1=wait( &status)) != -1){
printf("[Parent] Reaped %d\n", pid1);
}
return 0;
}

Trap signal using kill in child process?

Working on Linux, I want to catch the signal I have sent using kill in the child process and then print the loop but I don't know how.
I can't seem to get my code that catches the signal.
Here is my code so far:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int SHMSIZE = 9;
int alarmFlag = 0;
void main()
{
int shmid;
int *shm;
pid_t pid = fork();
if(pid == 0) {
pause();
shmid = shmget(4000, SHMSIZE, 0);
shm = shmat(shmid,0,0);
int i;
for(i=0;i<SHMSIZE;i++)
printf("<%d , ",shm[i]);
}
else
{
int *n;
shmid = shmget(4000,SHMSIZE,0666 | IPC_CREAT);
shm = shmat(shmid,0,0);
n = shm;
int i;
for(i=0;i<SHMSIZE;i++)
n[i] = i;
int result = kill(pid, SIGUSR1);
wait(NULL);
}
}
The pause() in your program on its own doesn't catch a signal, it just sleeps until a signal is delivered, but if that signal isn't caught (using sigaction() or signal(), as Jonathan Leffler wrote), it terminates the process. So, you have to add e. g. signal(SIGUSR1, catch); before pause(); and
void catch(int signum) { }
before main().

C Read from pipe blocks until child is terminated

Parent process creates N children each one replaces itself with exec. There is a communication between parent and exec through an array of pipes (int pipefd[N][2];)
The exec writes to the pipe with these commands:
char msg[50];
sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
printf("%s\n",msg);
write(i1, msg, strlen(msg)+1);
and the parent reads with these:
for (i=0;i<N;i++) {
close(pipefd[i][1]); // close the write end of the pipe in the parent
read(pipefd[i][0], buffer, sizeof(buffer));
printf("\n-C-\n");
if (buffer[0] == '\t'){
printf("%s\n",buffer);
}
int j;
for (j=0; j<100; j++) {
buffer[j]='\n';
}
close(pipefd[i][0]);
}
Now the problem is that only after the child is terminated the read gets unblocked and prints the buffer.
What I want to do is print the buffer immediately after the exec writes to the pipe.
Below is the all the code:
Parent File:
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#define N 5
pid_t *pid;
int pipefd[N][2];
int flag = 0;
int count_ctrl_c = 0;
void signal_handler(int sig){
signal(sig, SIG_IGN);
printf("\n");
flag = 1;
signal(SIGINT, signal_handler);
}
int main(int argc, char *argv[]) {
int i;
for (i = 0; i < N; i++) {
pipe(pipefd[i]);
}
int parent_pid = getpid();
pid= (pid_t *)malloc(N * sizeof(pid_t));
for (i = 0; i < N; i++) {
pid[i] = fork();
if (pid[i] == 0) //The parent process will keep looping
{
char b[50];
sprintf( b, "%d", i+1);
char i0[50];
sprintf( i0, "%d", pipefd[i][0]);
char i1[50];
sprintf( i1, "%d", pipefd[i][1]);
char par_id[50];
sprintf( par_id, "%d", parent_pid);
execl("***the/path/to/exec/calculate***", b,i0,i1,par_id,NULL);
}
}
if (parent_pid == getpid()) {
signal(SIGINT, signal_handler);
while(1){
if (flag){
printf("\n-A-\n");
char buffer[100];
int i;
for (i=0;i<N;i++) {
// Apostellei to shma SIGUSR2 se ola ta paidia tou
kill(pid[i], SIGUSR2);
}
printf("\n-B-\n");
for (i=0;i<N;i++) {
close(pipefd[i][1]); // close the write end of the pipe in the parent
read(pipefd[i][0], buffer, sizeof(buffer));
printf("\n-C-\n");
if (buffer[0] == '\t'){
printf("%s\n",buffer);
}
int j;
for (j=0; j<100; j++) {
buffer[j]='\n';
}
close(pipefd[i][0]);
}
//exit(0);
printf("finished reading\n");
flag = 0;
count_ctrl_c++;
if (count_ctrl_c == 2) {
exit(0);
}
}
}
}
}
calculate.c
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#define N 5
int i0,i1,parent_pid;
int flag = 0;
int time_to_term = 0;
double pi;
void signal_handler2(int sig);
void signal_handler(int sig);
void signal_handler2(int sig){
signal(sig, SIG_IGN);
signal(SIGALRM, SIG_IGN);
flag = 1;
signal(SIGUSR2, signal_handler2);
signal(SIGALRM, signal_handler);
}
void signal_handler(int sig){
signal(sig, SIG_IGN);
pid_t pid = getpid();
printf("time: %d, pid: %d, pi: %1.10f\n", time_to_term, pid, pi);
exit(0);
}
int main(int argc, char *argv[]) {
int pid;
signal(SIGINT, SIG_IGN);
signal(SIGUSR2, signal_handler2);
signal(SIGALRM, signal_handler);
time_to_term = atoi(argv[0]);
alarm(time_to_term);
i0 = atoi(argv[1]);
i1 = atoi(argv[2]);
parent_pid = atoi(argv[3]);
double mul = 1.0;
double par = 2.0;
pi = 3.0;
while(1){
pi = pi + (mul * (4.0 / (par * (par + 1.0) * (par + 2.0))));
mul = mul * (-1.0);
par += 2;
sleep(1);
if (flag) {
signal(SIGALRM, SIG_IGN);
close(i0);
char msg[50];
sprintf( msg, "\tsent from pid: %d, pi= %f", getpid(), pi);
printf("%s\n",msg);
write(i1, msg, strlen(msg)+1);
close(i1);
flag = 0;
signal(SIGALRM, signal_handler);
//exit(0);
}
}
}
General tip for troubleshooting this: Run both sides of the pipeline using the strace tool (you can use strace -f to follow forks) so that you can verify what is actually written / read from the pipe.
I suspect that in this case, nothing is written by the child! This is because the stdio layer that you use (printf()) checks whether it is writing to a terminal or to, well, anything else. In case of terminal, it flushes the output after each newline, but in other cases, it flushes only after a large-ish block of data is written (8KiB on GNU systems). Try flushing the output manually using fflush() after printf(). If that helps, you can adjust stdout buffering mode using setvbuf().
IMHO, your design is not really good as all child processes inherit all pipes you created and this is a waste of system resources. The right thing to do would be:
In the parent process:
dup fd's #0 and #1 to preserve for later use by the parent process; use fcntl with F_DUPFD_CLOEXEC on these new fd's to prevent inheritance on exec
close fd #0
close fd #1
create a pipe
prevent inheritance of the read fd of the pipe as said above
dup2 write fd of the pipe to make it fd #1; close the original write fd
fork & exec the child process
repeat steps 3 through 7 for all necessary children
dup2 stored duplicates of original fd's #0 and #1 back to #0 and #1 to restore the printf/scaf functionality
use select to poll read fd's of all pipes and possibly #0 if you expect any input on #0
If two-way communication is required then at step 4 create two pipes with appropriate adjustments to the described procedure and repeat steps 2 through 7 to create children.
In the child process (after exec)
Do all processing as required. Write to the parent either using fd #1 or printf or whatever.
Child process may always obtain its parent PID with getppid()
Your operating system is probably buffering the write.
Try using ioctl and FLUSHW to explicitly flush the pipe after the call to write. Also, check your return values in case something insidious is happening. See http://pubs.opengroup.org/onlinepubs/7908799/xsh/ioctl.html for more reading on ioctl.

why only my first x forks make the job (gcc)

This is from my study guide. From my perspective this is almost done but I can't put it working in the way I want.
The exercise is:
given an string fork X times and print one character per child until the the string finish.
This is the code and compiles:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
// SOME PROGRAM CONSTANTS
#define CHILD_QUANTITY 5
#define FIFO_FILE "/tmp/printer.fifo"
#define STRING_TO_PRINT "hola mundo como estas!!!!"
#define DELAY_TIME 2 // two seconds
// SOME GLOBAL VARIABLES
int fdfifo, next_printer = 0, next_char = 0;
pid_t printers[CHILD_QUANTITY];
void process_call_printer(int sig) {
char char_to_print;
if (read(fdfifo, &char_to_print, sizeof(char)) == -1) {
perror(__FUNCTION__);
}
// print the char
printf("[%d] -> %c\n", getpid(), char_to_print);
// alert the parent process about it
kill(getppid(), SIGUSR2);
// just wait for another signal
while(1) {
pause();
}
}
void process_call_hub(int sig) {
pid_t printer;
if (next_char < strlen(STRING_TO_PRINT)) {
if (write(fdfifo, &STRING_TO_PRINT[next_char], sizeof(char)) == -1) {
perror(__FUNCTION__);
}
alarm(DELAY_TIME);
if (next_printer >= CHILD_QUANTITY) {
next_printer = 0;
}
printer = printers[next_printer];
next_printer++;
next_char++;
printf("sending char %c to the printer %d\n", STRING_TO_PRINT[next_char - 1], next_printer - 1);
kill(printer, SIGUSR1);
}
else {
kill(getpid(), SIGQUIT);
}
}
void process_callback(int sig) {
// alarm(0);
printf("a callback function call\n");
// kill(getpid(), SIGALRM);
// while(1) {
// pause();
// }
}
void system_shutdown(int sig) {
printf("SIGQUIT recived...terminating\n");
if (unlink(FIFO_FILE) == -1) {
perror(__FUNCTION__);
}
close(fdfifo);
}
int main(void) {
pid_t pid;
int i;
if (mkfifo(FIFO_FILE, 0777) == -1) {
perror("pipe()");
return -1;
}
fdfifo = open(FIFO_FILE, O_RDWR, 0777);
if (fdfifo == -1) {
perror("open()");
return -2;
}
for (i = 0; i < CHILD_QUANTITY; i++) {
pid = fork();
printers[i] = pid;
switch(pid) {
case -1:
perror("Error\n");
break;
case 0:
// printer
signal(SIGUSR1, process_call_printer);
while(1) {
pause();
}
break;
default:
// hub
// do nothing.. we will figure out later...
break;
}
}
signal(SIGALRM, process_call_hub);
signal(SIGQUIT, system_shutdown);
signal(SIGUSR2, process_callback);
alarm(DELAY_TIME);
while(1) {
pause();
}
}
and this is the output I got
gabriel#GaboMac:20090918$ ./threaded_printer
sending char h to the printer 0
[1397] -> h
a callback function call
sending char o to the printer 1
[1398] -> o
a callback function call
sending char l to the printer 2
[1399] -> l
a callback function call
sending char a to the printer 3
[1400] -> a
a callback function call
sending char to the printer 4
[1401] ->
a callback function call
sending char m to the printer 0
sending char u to the printer 1
sending char n to the printer 2
sending char d to the printer 3
sending char o to the printer 4
sending char to the printer 0
sending char c to the printer 1
sending char o to the printer 2
sending char m to the printer 3
sending char o to the printer 4
sending char to the printer 0
sending char e to the printer 1
sending char s to the printer 2
sending char t to the printer 3
sending char a to the printer 4
sending char s to the printer 0
sending char ! to the printer 1
sending char ! to the printer 2
sending char ! to the printer 3
sending char ! to the printer 4
SIGQUIT recived...terminating
All echos should be like the five first ones.
Any idea?
Firstly, this is terrible code. You should never do real work in a signal handler. This program has its main loop in a signal handler - not good!
The problem is that your child processes do their work in the process_call_printer() signal handler, but that function never returns. It ends with
// just wait for another signal
while(1) {
pause();
}
Well, it's going to wait forever for another signal because a signal is blocked while it is being handled. So your child is not going to receive any more SIGUSR1s until it's finished processing the first one - and it never does.
That's why your child processes stop responding after they've handled the first signal.
Now, seriously. Go and rewrite this with the bare minimum of signal handling. It's usually done something like this...
int got_signal;
void handler(int) {
got_signal = 1;
}
int main() {
...
/* Wait for signal */
got_signal = 0;
while(!got_signal) {
sleep(1);
}
/* Signal has arrived - do something... */
...
}

Resources