Hello-
I'm trying to write a classic producer/consumer program using signals. My parent process (producer.c) forks and executes a new child program (consumer.c). The producer copies values from an input file (100 total int values to copy) to a common file, then sends a signal to the child to copy the value from the common file into an output file. Then the producer pauses. After it copies a value from the common file and puts it into the output file, the consumer signals the producer to put the next value in the common file, then pauses. Then the producer handles this signal and copies the next value from the input file, and so on. As it stands now, the transfer is inconsistent, but I don't know why. It usually quits after only a couple of values have been copied, sometimes 30, sometimes 50, etc. But rarely do all 100 values get copied from the input file. It seems random. I don't know how to make it consistently copy all 100 values without terminating prematurely. As you can see from my signal set, I've blocked every signal except SIGUSR1 & SIGUSR2. I thought this was the key, but the point of failure always occurs right after the child has handled the SIGUSR2 signal and is about to continue its loop to copy more values from common. I thought I covered my bases with this one. I've had my nose in books for hours trying to find the answer to this problem + now I'm so dizzy I can't think. If anybody could offer a hint, I'd be grateful.
Thank you.
/* producer.c
*
*/
#include <stdio.h>
.....
.....
.....
void signalhandler();
int main(int argc, char *argv[])
{
const char *common_file = "/tmp/common";
const char *input_file = /home/echobase/input";
const char *child_path = /home/echobase/consumer";
int input_file_desc;
int common_file_desc;
int save_errno;
int bytes_to_read = 4;
int n; //bytes to transfer
char buf[BUFSIZ];
pid_t pid;
pid_t child_pid;
struct sigaction sighandler;
sigset_t blocked;
void sigusrhandler();
sighandler.sa_handler = sigusrhandler;
sighandler.sa_flags = SA_RESTART;
sigfillset(&blocked);
sigdelset(&blocked, SIGUSR1);
sighandler.sa_mask = blocked;
if(sigaction(SIGUSR1, &sighandler, 0) == -1)
perror("sigaction");
/* open the input file */
input_file_desc = open(input_file, O_RDONLY);
if(input_file_desc == -1) {
save_errno = errno;
printf("Open failed with error %d\n", save_errno);
}
/* create child process */
if((child_pid = fork()) < 0) {
fprintf(stderr, "fork error");
}else if(child_pid == 0) {
execlp(child_path, "consumer", 0);
}
/* loop to transfer values from input file to common file */
while((n = read(input_file_desc, buf, bytes_to_read)) > 0)
{
printf("parent is in loop1\n");
if((common_file_desc = open(common_file, O_RDWR)) == -1){
perror("open");
exit(1);
}
lseek(common_file_desc, 0L, 0);
write(common_file_desc, buf, n);
close(common_file_desc);
printf("parent is in loop2\n");
kill(child_pid, SIGUSR2);
pause();
}
close(input_file_desc);
printf("parent test successful\n");
exit(0);
}
void sigusrhandler()
{
printf("parent called with signal\n");
//sleep(2);
//printf("parent done handling signal\n");
}
/* consumer.c
*
*/
#include <stdio.h>
....
....
....
void signalhandler();
int main(int argc, char *argv[])
{
const char *common_file = "/tmp/common";
const char *output_file =/home/output";
int common_file_desc;
int output_file_desc;
int save_errno;
int bytes_to_read = 4;
int n; //bytes to transfer
char buf[BUFSIZ];
int tries = 100;
pid_t parent_id = getppid();
struct sigaction sighandler;
sigset_t newmask;
void sigusrhandler();
sighandler.sa_handler = sigusrhandler;
sighandler.sa_flags = SA_RESTART;
sigfillset(&newmask);
sigdelset(&newmask,SIGUSR2);
sighandler.sa_mask = newmask;
if(sigaction(SIGUSR2, &sighandler, 0) == -1)
perror("sigaction");
/* open the output file */
if((output_file_desc = open(output_file, O_WRONLY, 0)) == -1) {
save_errno = errno;
printf("Open failed with error %d\n", save_errno);
exit(1);
}
pause();
/* loop to copy values from common file to output file */
while(tries--){
//pause();
/* open the common file */
if((common_file_desc = open(common_file, O_RDWR)) == -1){
perror("open");
exit(1);
}
/* copy bytes from common file to output file */
if((n = read(common_file_desc, buf, bytes_to_read)) > 0){
write(output_file_desc, buf, n);
}
close(common_file_desc);
printf("child is in loop\n");
kill(parent_id, SIGUSR1);
pause();
}
printf("child test successful\n");
close(output_file_desc);
exit(0);
}
void sigusrhandler()
{
printf("child called with signal\n");
//sleep(2);
//printf("child done handling signal\n");
}