Reputation: 181
I have a simple setup for a fork and pipe that I have used before. But this time around I'm getting a SIGPIPE
in my write
call. Here's the code
int fd[2];
int pid;
if (pipe(fd) == -1) {
perror("pipe init error");
exit(1);
}
// signal(SIGPIPE, SIG_IGN);
if ((pid = fork()) < -1) {
perror("fork error"); exit(1);
}
// parent
else if (pid > 0) {
close(fd[0]);
write(fd[1], "WHAT", MAXWORD); //SIGPIPE here
close(fd[1]);
int status;
wait(&status);
}
// child
else {
close(fd[1]);
// void foo(char *dirname, int in, int out);
// foo takes a path, reads from fd 'in' and outputs to 'fd' out
foo("./some/path", fd[0], 1);
close(fd[0]);
}
Here's function foo:
void foo(char *dirname, int in, int out){
int string_length;
char word[MAXWORD];
// to get rid of \n
char* sep;
sep = malloc(sizeof(char));
// read from piped stdin until it's closed
while ((string_length = read(in, word, MAXWORD)) > 0){
// get rid of \n
sep = strchr(word, '\n');
*sep = '\0';
printf("THe word is: %s\n", word);
}
}
Upvotes: 1
Views: 1895
Reputation: 753705
If you get SIGPIPE when you write on a pipe, it means there is no process that can read from the pipe: neither the current process (you've close the read end of the pipe — which is good; you'd be deadlocked instead of dead if you'd not closed it) nor the other (child) process.
Since you've not shown what the function foo()
does, we can't tell you any more about what's wrong.
Now that foo()
has been added, it is not clear what's up. There are issues, but most are not show stoppers.
dirname
is unused.out
is unused.sep
in the loop.I suspect item 4 is the immediately critical issue; the others are more matters of tidiness.
I note that in the main code, you have:
write(fd[1], "WHAT", MAXWORD); //SIGPIPE here
Unless MAXWORD
is either 4 or 5, you are on a losing path; you should only write 4 or 5 characters.
Combined with the read()
...the read will attempt to read MAXWORD bytes but might get fewer. However, there's no sign that the data written contains a newline, so the search for a newline in the input is not going to work reliably. However, that problem should manifest itself after the pipe was successfully written too, not before.
I note that the variable int fd_parent_write_word[2];
is unused and the code uses variable int fd[2]
without declaring it.
It is a nuisance when what you get to analyze is not an SSCCE (Short, Self-Contained, Correct Example). It is so much easier when the test case has been reduced to a simple program that can be compiled and run with the submitter confident that the problem reproduces with it.
This SSCCE code compiles cleanly and runs OK:
#include <assert.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
enum { MAXWORD = 5 };
static void foo(int in);
static void he_who_pays_the_piper(int signum)
{
assert(signum == SIGPIPE);
const char msg[] = "Received signal SIGPIPE\n";
write(2, msg, sizeof(msg)-1);
exit(1);
}
int main(void)
{
int fd[2];
int pid;
if (pipe(fd) == -1) {
perror("pipe init error");
exit(1);
}
signal(SIGPIPE, he_who_pays_the_piper);
if ((pid = fork()) < -1) {
perror("fork error"); exit(1);
}
else if (pid > 0) {
close(fd[0]);
write(fd[1], "WHAT", MAXWORD); //SIGPIPE here
close(fd[1]);
int status;
pid = wait(&status);
printf("Got status 0x%04X from %d\n", status, pid);
}
else {
close(fd[1]);
foo(fd[0]);
close(fd[0]);
}
return 0;
}
static void foo(int in)
{
int string_length;
char word[MAXWORD];
while ((string_length = read(in, word, MAXWORD)) > 0)
printf("The word is: %.*s\n", string_length, word);
}
Example output:
The word is: WHAT
Got status 0x0000 from 49458
Note that this works because the '\0'
at the end of the string WHAT
is written to the pipe, and read from the pipe. Most usually, you do not write the strings including the trailing '\0'
.
Upvotes: 2