Getting an error while executing the below program in c - c

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main ()
{
/* Create the pipe */
pid_t pid;
int k;
pid = fork ();
if (pid < 0)
{
printf ("Fork Failed\n");
return -1;
}
for(k=0;k<60;k++)
{
if (pid == 0)
{
printf("I'm the child\n");
printf("my pid is %d\n",getpid());
FILE *fp,*fp1;
int i;
/* open the file */
fp = fopen("File1.txt ", "r");
fscanf(fp, "%d", &i) ;
printf("i: %d and pid: %d",i,pid);
fclose(fp);
fp1= fopen("File1.txt ", "w");
fprintf(fp, "%d", i++);
fclose(fp1);
sleep(1);
}
else
{
printf("I'm the parent\n");
printf("my pid is %d\n",getpid());
FILE *fp,*fp1;
int i;
int y;
/* open the file */
fp = fopen("File1.txt ", "r");
fscanf(fp, "%d", &i) ;
printf("i: %d and pid: %d",i,pid);
fclose(fp);
fp1= fopen("File1.txt ", "w");
fprintf(fp, "%d", i++);
fclose(fp1);
sleep(1);
}
}
return 0;
}
I got an error i.e segmentation fault core dumped after executing this code. I would like to know where I did wrong. My main motto is: I want to read a file that contains a number 1and print that number.
I want to write the same file and increment that number by 1.After that the child or parent goes into sleep mode and then parent or child performs the same procedure again. This process continues up to 60 times .

You are writing to the wrong file descriptor in both parent and child.
The following line:
fprintf(fp, "%d", i++);
should be:
fprintf(fp1, "%d", i++);
Indeed you have already closed fp before.

Related

Multi Thead by using fork() with shared pipe, data sometimes get overwritten by different Child before read

int main(int argc, char **argv)
{
int k=0,i=0;
int status;
char x[100],a[100];
int fd[2];
pipe(fd);
//printf("number = %d\n",argc);
for(i=1;i<argc;i++){
if(fork()==0){
//printf("Child pid=%d\n",getpid());
close(fd[0]);
double s,temp=0.0;
int count=0;
FILE *file;
file = fopen(argv[i], "r");
//printf("!!!Handle file %s\n",argv[i]);
while(!feof(file)){
//printf("--Scaning\n");
fscanf(file,"%lf ",&temp);
s+=temp;
count++;
//printf("++Counting:%d\n",count);
}
printf("Child PID=%d of Parent PID=%d, finished handle file %s with sum=%lf and count=%d.\n",getpid(),getppid(),argv[i],s,count);
sprintf(a,"%lf %d %s",s,count,argv[i]);
//printf("%s + %s",a,argv[i]);
fclose(file);
write(fd[1], a, (strlen(a)+1));
close(fd[1]);
return 0;
}
//else{
//printf("Total: %d\n",argc);
//}
}
close(fd[1]);
int countsum,tempcount=0;
double tempsum,ave,sum=0.0;
char name[100];
for (i = 1; i < argc ; i++){
//printf("\nParent PID=%d, and now Waiting.\n", getpid());
//wait(&status);
//printf("Child Exit Code = %d\n\n",status);
read(fd[0],x,sizeof(x));
sscanf(x,"%lf %d %s",&tempsum,&tempcount,name);
printf("%s SUM=%lf NUM=%d AVG=%lf\n",name,tempsum,tempcount,tempsum/tempcount);
sum+=tempsum;
countsum+=tempcount;
}
printf("AVERAGE=%lf\n",sum/countsum);
return 0;
}
Source Code attached, sometimes child process will overwrite the result from other child before that result getting read, I can not use a static number of pipes since the question require the code work with any number of input.
dataset1 SUM=8212.128970 NUM=171 AVG=48.024146
dataset2 SUM=5386.242610 NUM=99 AVG=54.406491
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917
AVERAGE=50.478198
Some times it gets things like this:
dataset2 SUM=5386.242610 NUM=99 AVG=54.406491
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917
dataset3 SUM=6845.298770 NUM=135 AVG=50.705917
[root#localhost CacheDrive]#
Output
Solved by assigning a fixed value for write and read size, like this:
char x[MAXARGU_SIZE*argc];
char a[MAXARGU_SIZE];
and scan the results by a char* which move right by MAXARGU_SIZE each time, read results one by one. like such
for (i = 1; i < argc ; i++){
wait(NULL);
}
int scaning=0;
char* ptc=x;
read(fd[0],x,sizeof(x));
for (i = 1; i < argc ; i++){
//printf("\nParent PID=%d, and now Waiting.\n", getpid());
//wait(&status);
//printf("Child Exit Code = %d\n\n",status);
scaning+=MAXARGU_SIZE;
sscanf(ptc,"%lf %d %s\0",&tempsum,&tempcount,name);
ptc=&x[scaning];
printf("%s SUM=%lf NUM=%d AVG=%lf\n",name,tempsum,tempcount,tempsum/tempcount);
sum+=tempsum;
countsum+=tempcount;
}

getting free(): invalid size when executing code

compiling with gcc hw2.c -o x -lpthread
free(): invalid size
free(): invalid size
free(): invalid size
nano infile.txt
I'm assuming it has something to do with the file pointer maybe? the semaphores have been commented out to fix this issue first. All answers point to the pointer but switching things up isn't much help. I've tried compiling differently that doesn't help either.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
//sem_t X;
void process(){
//sem_open("X", O_CREAT,0777,0);
int ret;
int N = 1;
pid_t pid;
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile);
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w");
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile);
}
printf("\n");
int c;
//sem_getvalue(&X,&c);
printf(" \n \n \n%d",c);
}
int main(){
int pid, pid1, pid2;
pid = fork();
if(pid == 0){
//child1, Last
printf("Starting Process C: ");
process();
}
else{
pid1 = fork();
if(pid1 == 0){
//child2, Middle
printf("Starting Process B: ");
process();
}
else{
pid2 = fork();
if(pid2 == 0){
//child 3, First
printf("Starting Process A: ");
process();
}
else{
}
}
}
//sem_close(&X);
//sem_unlink(&X);
}
The most obvious problem is in your loop. I've removed everything but the fopen and fclose calls:
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fclose (infile);
infile = fopen("infile.txt", "w");
fclose(infile);
}
As you probably now see, when i is 1, you try to fclose(infile) - but that isn't open, hence the errors you get.
You need to move the first fopen into the loop - and check that opening the file and reading from it succeeds too:
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
void process() {
int N = 1;
for(int i = 0; i < 50; i++) {
FILE* infile = fopen("infile.txt", "r");
if(infile) {
bool readok = fscanf(infile, "%d", &N) == 1;
fclose(infile);
if(readok) { /* only do this if a value was read from the file ok */
printf("N: %d Process ID: %d", N, getpid());
infile = fopen("infile.txt", "w");
if(infile) {
N++;
fprintf(infile, "%d", N);
fflush(infile);
fclose(infile);
}
}
}
}
printf("\n");
exit(0); /* terminate this sub process */
}
int main() {
const size_t kPids = 3;
pid_t pids[kPids]; /* simplify keeping a number of background processes */
for(size_t i = 0; i < kPids; ++i) {
pids[i] = fork();
if(pids[i] == 0) {
printf("Starting Process %c:\n", (char)('A' + i));
process();
}
}
/* wait for children to finish */
pid_t pid;
int wstatus;
while((pid = wait(&wstatus)) != -1) {
printf("pid %d is done with status %d\n", pid, wstatus);
}
}
Your loop is problematic
FILE* infile = fopen ("infile.txt", "r"); //1
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile); //2
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w"); //3
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile); //4
}
You open the file at 1, then enter the loop, close it at 2, re-open it at 3 and re-close it at 4. In the next iteration, when you attempt to close at 2, you would hit into a double-free as it's already been closed at 4.

Scanf in while loop not able to input anything

I'm using a Linux 2.0.26 VM and never have this problem.
The while loop works because I added a printf inside it in order to test it.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
int i;
mknod("pipe.txt", S_IFIFO | 0666, 0);
for (i = 0; i < 2; i++) {
if (fork() == 0) {
if (i == 0)
to_pipe();
//else
// pipe_a_archivo();
}
}
wait(NULL);
unlink("pipe.txt");
}
void to_pipe()
{
int num, fdini;
fdini = open("pipe.txt", O_WRONLY);
do {
//printf("Test");
scanf("%d", &num);
write(fdini, &num, sizeof(int));
} while (num != 0);
close(fdini);
unlink("pipe.txt");
exit();
}
This program should get numbers from keyboard and write them in a file. My problem is that whenever I execute the program from the command line, nothing happens, scanf() doesn't work because it doesn't let me input any number. I know for sure that the loop works because if uncomment printf() it prints on the screen. Any help on solving this problem?
I think that most of your problem is due to you not implementing the pipe_a_archivo() function to read from the FIFO and write the data to a file. Certainly, the code in the question is not a good MCVE (Minimal, Complete, Verifiable Example). Amongst other problems, there is no action for the second iteration of the loop.
This code error checks function calls, and includes a plausible implementation of pipe_a_archivo(), and then works sensibly:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
static void to_pipe(void);
static void pipe_a_archivo(void);
#define FIFO_NAME "pipe.txt"
#define FILE_NAME "archive.txt"
int main(void)
{
if (mkfifo(FIFO_NAME, 0666) != 0)
{
fprintf(stderr, "failed to create FIFO '%s'\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
if (fork() == 0)
to_pipe();
if (fork() == 0)
pipe_a_archivo();
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("PID %d exited with status 0x%.4X\n", corpse, status);
unlink("pipe.txt");
}
static void to_pipe(void)
{
int num, fdini;
fdini = open(FIFO_NAME, O_WRONLY);
do
{
printf("Enter a number: ");
fflush(stdout);
scanf("%d", &num);
write(fdini, &num, sizeof(int));
} while (num != 0);
close(fdini);
exit(0);
}
static void pipe_a_archivo(void)
{
int fd_in = open(FIFO_NAME, O_RDONLY);
if (fd_in < 0)
{
fprintf(stderr, "Failed to open FIFO '%s' for reading\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
FILE *fp_out = fopen(FILE_NAME, "w");
if (fp_out == NULL)
{
fprintf(stderr, "Failed to open file '%s' for writing\n", FILE_NAME);
exit(EXIT_FAILURE);
}
int num;
while (read(fd_in, &num, sizeof(num)) == sizeof(num))
{
fprintf(fp_out, "%d\n", num);
}
close(fd_in);
fclose(fp_out);
exit(0);
}
I removed the loop in main() because a loop that tests which iteration it is on and then calls an appropriate function is really not a good design. This code also only deletes the FIFO in the main program, and only after both child processes have exited.
Sample run:
$ ./fifo29
Enter a number: 23
Enter a number: 34
Enter a number: 12931344
Enter a number: 0
PID 10939 exited with status 0x0000
PID 10940 exited with status 0x0000
$ cat archive.txt
23
34
12931344
0
$

Unable to send a message from a child process back to the parent process

I am trying to understand how pipes and forking work. So I wrote a simple program where a parent process sends a message to the child process (which works fine). But if I try to send a message back from the child process by adding the commented code, it stops working. And the execution of the program stops after outputting "Parent sent: hello".
int main() {
int child_to_parent[2];
int parent_to_child[2];
pipe(child_to_parent);
pipe(parent_to_child);
pid_t id = fork();
if (id == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
FILE* out = fdopen(child_to_parent[1], "w");
FILE* in = fdopen(parent_to_child[0], "r");
char msg[6];
fscanf(in ,"%s", msg);
printf("Child got: %s\n", msg);
/*
fprintf(out, "hi ");
printf("Child sent: hi\n");
*/
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
FILE* in = fdopen(child_to_parent[0], "r");
FILE* out = fdopen(parent_to_child[1], "w");
fprintf(out, "hello");
printf("Parent sent: hello\n");
/*
char msg[3];
fscanf(in, "%s", msg);
printf("Parent got: %s\n", msg);
*/
}
}
And I can't figure out why. What confuses me the most is why the child process can't even receive the message after I modified the code. Could anyone please tell me what's wrong, or direct me in the right direction?
First solution using read/write to exchange any number of messages
Here I indicate the end of each buffer to read by a \n :
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void rd(int fd, int child)
{
char c;
int first = 1;
do {
if (!read(fd, &c, 1))
break;
if (first) {
printf("%s got:", (child) ? "Child" : "Parent");
first = 0;
}
putchar(c);
} while (c != '\n');
}
void wr(int fd, const char * msg, int child)
{
write(fd, msg, strlen(msg));
printf("%s sent:%s", (child) ? "Child" : "Parent", msg);
}
int main() {
int child_to_parent[2];
int parent_to_child[2];
pipe(child_to_parent);
pipe(parent_to_child);
pid_t id = fork();
if (id == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
rd(parent_to_child[0], 1);
wr(child_to_parent[1], "hi\n", 1);
rd(parent_to_child[0], 1);
wr(child_to_parent[1], "fine, and you ?\n", 1);
rd(parent_to_child[0], 1);
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
wr(parent_to_child[1], "hello\n", 0);
rd(child_to_parent[0], 0);
wr(parent_to_child[1], "how are you ?\n", 0);
rd(child_to_parent[0], 0);
wr(parent_to_child[1], "fine too\n", 0);
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra p.c
pi#raspberrypi:/tmp $ ./a.out
Parent sent:hello
Child got:hello
Child sent:hi
Parent got:hi
Parent sent:how are you ?
Child got:how are you ?
Child sent:fine, and you ?
Parent got:fine, and you ?
Parent sent:fine too
Child got:fine too
It is also possible to use fread/fwrite, fflush is necessary after fwrite to not be blocked. It is fortunately not necessary to close the pipe after sending to be able to read and answer, else only one message can be exchanged. I still use \n to indicate the end of the buffer sent :
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void rd(FILE * fd, int child)
{
char c;
int first = 1;
do {
if (!fread(&c, 1, 1, fd))
break;
if (first) {
printf("%s got:", (child) ? "Child" : "Parent");
first = 0;
}
putchar(c);
} while (c != '\n');
}
void wr(FILE * fd, const char * msg, int child)
{
fwrite(msg, strlen(msg), 1, fd);
fflush(fd);
printf("%s sent:%s", (child) ? "Child" : "Parent", msg);
}
int main() {
int child_to_parent[2];
int parent_to_child[2];
pipe(child_to_parent);
pipe(parent_to_child);
pid_t id = fork();
if (id == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
FILE* out = fdopen(child_to_parent[1], "w");
FILE* in = fdopen(parent_to_child[0], "r");
rd(in, 1);
wr(out, "hi\n", 1);
rd(in, 1);
wr(out, "fine, and you ?\n", 1);
rd(in, 1);
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
FILE* in = fdopen(child_to_parent[0], "r");
FILE* out = fdopen(parent_to_child[1], "w");
wr(out, "hello\n", 0);
rd(in, 0);
wr(out, "how are you ?\n", 0);
rd(in, 0);
wr(out, "fine too\n", 0);
}
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra pp.c
pi#raspberrypi:/tmp $ ./a.out
Parent sent:hello
Child got:hello
Child sent:hi
Parent got:hi
Parent sent:how are you ?
Child got:how are you ?
Child sent:fine, and you ?
Parent got:fine, and you ?
Parent sent:fine too
Child got:fine too
And finally if you want to use fscanf("%s", ...) you need to sent a separator (a space or \n for instance) after the word to not block fscanf and of course to also read the separator character, the fflush is necessary after the fwrite.
If I change a little you program :
#include <stdio.h>
#include <unistd.h>
int main() {
int child_to_parent[2];
int parent_to_child[2];
pipe(child_to_parent);
pipe(parent_to_child);
pid_t id = fork();
if (id == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
FILE* out = fdopen(child_to_parent[1], "w");
FILE* in = fdopen(parent_to_child[0], "r");
char msg[16], c;
fscanf(in ,"%s%c", msg, &c);
printf("Child got: %s\n", msg);
fprintf(out, "hi ");
fflush(out);
printf("Child sent: hi\n");
fscanf(in ,"%s%c", msg, &c);
printf("Child got: %s\n", msg);
fprintf(out, "fine,you? ");
fflush(out);
printf("Child sent: fine,you?\n");
fscanf(in ,"%s%c", msg, &c);
printf("Child got: %s\n", msg);
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
FILE* in = fdopen(child_to_parent[0], "r");
FILE* out = fdopen(parent_to_child[1], "w");
fprintf(out, "hello\n");
fflush(out);
printf("Parent sent: hello\n");
char msg[16], c;
fscanf(in, "%s%c", msg, &c);
printf("Parent got: %s\n", msg);
fprintf(out, "how-are-you? ");
fflush(out);
printf("Parent sent: how-are-you?\n");
fscanf(in, "%s%c", msg, &c);
printf("Parent got: %s\n", msg);
fprintf(out, "fine-too ");
fflush(out);
printf("Parent sent: fine-too\n");
}
}
Compilation and execution :
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra ppp.c
pi#raspberrypi:/tmp $ ./a.out
Parent sent: hello
Child got: hello
Child sent: hi
Parent got: hi
Parent sent: how-are-you?
Child got: how-are-you?
Child sent: fine,you?
Parent got: fine,you?
Parent sent: fine-too
Child got: fine-too
fscanf reads until some whitespace character (as given by isspace) is found when you use %s, yet you're not sending one. So fscanf never returns, because it's waiting for the whitespace.
Use fread and fwrite instead of fscanf and fprintf and your pipes will work.
In both the parent and the child, when you have finished writing to the pipe, flush the buffers with fflush and close the pipe write ends with close.
Here is a slightly modified program:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
FILE *fdopen(int fd, const char *mode);
int main() {
int child_to_parent[2];
int parent_to_child[2];
pipe(child_to_parent);
pipe(parent_to_child);
pid_t id = fork();
if (id == 0) {
close(parent_to_child[1]);
close(child_to_parent[0]);
FILE* out = fdopen(child_to_parent[1], "w");
FILE* in = fdopen(parent_to_child[0], "r");
char msg[6];
printf("Child gonna read...\n");
fscanf(in ,"%s", msg);
printf("Child got: %s\n", msg);
fprintf(out, "hi");
fflush(out);
printf("Child sent: hi\n");
close(child_to_parent[1]);
} else {
close(parent_to_child[0]);
close(child_to_parent[1]);
FILE* in = fdopen(child_to_parent[0], "r");
FILE* out = fdopen(parent_to_child[1], "w");
fprintf(out, "hello");
printf("Parent sent: hello\n");
fflush(out);
close(parent_to_child[1]);
char msg[3];
printf("Parent gonna read...\n");
fscanf(in, "%s", msg);
printf("Parent got: %s\n", msg);
}
}
Output when I run it:
Parent sent: hello
Parent gonna read...
Child gonna read...
Child got: hello
Child sent: hi
Parent got: hi

Troubles with execlp's output and pipes

I'm writing a program that has an interface like:
myprog file1 file2 c
This program creates two children and P2 with an execlp opens file2, makes a grep -c on this file for founding c and gives the results to his brother P1 (I have to do it closing the STDOUT's FD and dupping the pipe p2p1 between them). P1 receives this from p2p1 and sends this value to P0. Moreover this also makes the same thing with file1 and gives the result to P0, which will print them.
The problem is: the father P0 reads something, but it is wrong.
What I'm supposed to do? Here's the code and thanks for your attention.
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define MAX_STRING_LENGTH 128
/**************************/
/* DICHIARAZIONE FUNZIONI */
/**************************/
void wait_child();
void processo_p2(char *inputfile, char *c);
void processo_p1(char *inputfile, char *c);
/*********************/
/* VARIABILI GLOBALI */
/*********************/
int p1p0[2], p2p1[2];
int main(int argc, char* argv[])
{
int pid[2], i, value, count=0;
char *c, buf[10];
if (argc !=4)
{
fprintf(stderr, "Numero di argomenti errato\n");
fprintf(stderr, "Usage: %s file1 file2 C\n", argv[0]);
exit(EXIT_FAILURE);
}
c=argv[3];
/* Init */
pipe(p1p0);
pipe(p2p1);
for (i=0; i<2; i++)
{
pid[i] = fork();
if (pid[i] < 0)
{
fprintf(stderr, "P0: Errore nella fork");
exit(EXIT_FAILURE);
}
else if (pid[i] == 0)
{
if (i==0) /*P1*/
{
close(p1p0[0]);
close(p2p1[1]);
sleep(1);
processo_p1(argv[1], c);
close(p2p1[0]);
close(p1p0[1]);
exit(EXIT_SUCCESS);
}
else if (i==1)
{
close(p2p1[0]);
close(p1p0[0]);
close(p1p0[1]);
processo_p2(argv[2],c);
close(p2p1[1]);
exit(EXIT_SUCCESS);
}
}
else
{
printf("P0: created child P%d with PID %d\n", i+1, pid[i]);
close(p2p1[0]);
close(p2p1[1]);
close(p1p0[1]);
}
}
i=0;
int nread;
while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
i++;
buf[i] = '\0';
printf("%s\n",buf);
for(i=0;i<2;i++)
{
wait_child();
}
return 0;
}
void processo_p2(char *inputfile, char *c)
{
int fd, nread, i=0, found=0;
char temp, row[100];
close(1);
dup(p2p1[1]);
execlp("grep", "grep", "-c", c, inputfile, (char *)0);
perror("P2: errorr in exec");
close(1);
}
void processo_p1(char *inputfile, char *c)
{
int fd, nrw, sk, nread, p2=0, i=0;
int value=1;
char temp, row[100], buf[10];
//RECEIVING DATA FROM P2 AND SENDING TO P0
while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
i++;
}
buf[i] = '\0';
printf("from p2: %s\n",buf); //NOTHING STAMPED
write(p1p0[1],&buf,strlen(buf)+1);
close(1);
dup(p1p0[1]);
execlp("grep", "grep", "-c", c, inputfile, (char *)0);
perror("P1: errore in exec");
close(p1p0[1]);
}
void wait_child() {
int pid_terminated,status;
pid_terminated=wait(&status);
if (pid_terminated < 0)
{
fprintf(stderr, "%d\n", getpid());
perror("P0: errore in wait");
exit(EXIT_FAILURE);
}
if(WIFEXITED(status))
{
printf("P0: terminazione volontaria del figlio %d con stato %d\n",
pid_terminated, WEXITSTATUS(status));
if (WEXITSTATUS(status) == EXIT_FAILURE)
{
fprintf(stderr, "P0: errore nella terminazione del figlio pid_terminated\n");
exit(EXIT_FAILURE);
}
}
else if(WIFSIGNALED(status))
{
fprintf(stderr, "P0: terminazione involontaria del figlio %d a causa del segnale %d\n",
pid_terminated,WTERMSIG(status));
exit(EXIT_FAILURE);
}
}
Trivia (but it stops the code compiling): The code shown originally has a close brace in the wrong place — the functions are all apparently embedded inside main(). The last brace should be moved up the file considerably.
In the loop that launches the child processs, you have the parent process execute:
printf("P0: created child P%d with PID %d\n", i+1, pid[i]);
close(p2p1[0]);
close(p2p1[1]);
close(p1p0[1]);
In the parent process, immediately after the loop, you have:
int nread;
while ( (nread = read(p2p1[0], &buf[i], sizeof(char)) ) > 0 ) {
i++;
buf[i] = '\0';
printf("%s\n",buf);
for(i=0;i<2;i++)
{
wait_child();
}
return 0;
}
'Tis a pity that you closed the file descriptor you're trying to read from. The parent should be reading from p1p0[0], which you did leave open.
Fixes:
Move the set of three closes out of the loop.
Read from the correct file descriptor.
Insert a missing close brace for the while loop shown, or remove its open brace.
The question in the comments has, as usual for comments, inscrutable code. The problem though is that you have too big a loop.
This is what the tail of my fixed version of your main() function looks like:
…rest of loop to launch children…
else
{
printf("P0: created child P%d with PID %d\n", i + 1, pid[i]);
}
}
close(p2p1[0]);
close(p2p1[1]);
close(p1p0[1]);
i = 0;
int nread;
while ((nread = read(p1p0[0], &buf[i], sizeof(char)) ) > 0)
i++;
buf[i] = '\0';
printf("%s\n", buf);
for (i = 0; i < 2; i++)
{
wait_child();
}
return 0;
}
Given that I saved the source code in a file pip.c and created the program pip from it, a sample run produced:
$ ./pip pip.c pip.c c
P0: created child P1 with PID 75458
P0: created child P2 with PID 75459
from p2: 49
49
P0: terminazione volontaria del figlio 75459 con stato 0
P0: terminazione volontaria del figlio 75458 con stato 0
$
I'm not entirely happy with all the newlines, but at least the same answer is given twice, as it obviously should be.

Resources