I'm trying to make a program that creates a file, writes 0 into it and then, using a child process, alternates the incrementation of that that value. For example, the child should increment that value to 1, and writes it back to the file. After this, the parent increments it to 2 and writes it in the file. The child to 3, and so on. Synchronization between the processes is done via signals. Here is the source code:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void sig_hand (int sig);
int fd;
int main()
{
pid_t pid;
int i;
fd = open ("abc.txt",O_RDWR|O_TRUNC);
if (fd == -1)
{
fd = creat ("abc.txt",S_IRUSR|S_IWUSR);
}
write (fd,"0",2);
if ((pid = fork()) < 0)
{
fprintf (stderr, "Error creating process\n");
exit (1);
} else
{
if (pid == 0)
{
signal (SIGUSR1,sig_hand);
for (;;)
{
pause();
kill (getppid(),SIGUSR1);
}
}
if (pid > 0)
{
sleep (1);
signal (SIGUSR1,sig_hand);
for (i=0;i<5;i++)
{
kill (pid,SIGUSR1);
pause ();
}
kill (pid,SIGTERM);
}
}
return 0;
}
void sig_hand (int sig)
{
int x;
char c;
read (fd,&c,2);
x=atoi(&c);
x++;
printf ("x=%d\n",x);
snprintf (&c,3,"%d",x);
lseek (fd,0,SEEK_SET);
printf ("PID %d is writing\n",getpid());
write (fd,&c,2);
}
Running this program produces the following output:
x=1
PID 4434 is writing
x=1
PID 4433 is writing
x=2
PID 4434 is writing
x=2
PID 4433 is writing
x=3
PID 4434 is writing
x=3
PID 4433 is writing
x=4
PID 4434 is writing
x=4
PID 4433 is writing
x=5
PID 4434 is writing
x=5
PID 4433 is writing
Why is the child and the parent incrementing the same value in one iteration?
Thanks!
Here is a corrected sig_hand
The problem isn't your synchronization, it's your file accesses. You read from the file, seek back to the beginning, and then write to the file. Where do you think the next read is going to come from? You need to seek back to the start of the file after every write, as well.
You also have some buffer overflows, because you are using a char as a single-character string. It doesn't work that way, because you don't have room for the null-terminator.
Your primary problem is that you can't time the signals that way. Your program deadlocked the first and every time I ran it. One program can (and often will) send the signal before the other is in a position to wait for it. You are completely dependent on the scheduler and you can't anticipate or predict it. So the proper procedure is to block the signal so it isn't delivered until you are ready to deal with it. The program below uses
sigrocmask
andsigsuspend
to accomplish that.Your second problem is the one Chris J. Kiick touched upon. You were reading and writing 2 bytes from a 1 byte memory location But, more importantly, the file descriptor is shared between the parent and the child so you need to seek to the proper position each time or the other process will leave it somewhere you weren't expecting.