Pipe Broken, FIFO file - c++

I'm trying a program to use FIFO file, but I'm getting Broken pipe as output. Here is the code -
#include<iostream>
#include<stdlib.h>
#include<fcntl.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
using namespace std;
int main(int argc,char *argv[])
{
int fd; //stores file descriptor returnd from open
char buf[256];
if(argc<2||argc>3)
{
cout<<"Invalid Arguments";
return 1;
}
mkfifo(argv[1],0777);
if(argc==3)
{
cout<<"Writer\n";
if((fd=open(argv[1],O_WRONLY))==-1)
{
perror("open");
return 1;
}
write(fd,argv[2],strlen(argv[2]));
sleep(10);
}
else
{ cout<<"Reader\n";
if((fd=open(argv[1],O_RDONLY|O_NONBLOCK))==-1)
{
perror("open");
return 1;
}
read(fd,&buf,sizeof(buf));
cout<<buf;
}
close(fd);
return 1;
}
Output:
Below Fifo is the name of the file and Hello is the content.
./a.out fifo hello &
Writer
./a.out fifo
Reader
[1]+ Broken pipe
I should get "Hello" as the output. Can anyone help?

Your write happens before you start your reader. When you write to a pipe and it has no reader you get SIGPIPE.
In this particular design, you need to handle SIGPIPE with retry logic.

The error you get is EPIPE and if you read a write manual you will see that you get EPIPE when
fd is connected to a pipe or socket whose reading end is closed.
You get this error because you open the reading end of the pipe in non-blocking mode, which means the read call will not block and wait for data to be received, instead when the read call immediately return you close the pipe and exit the process.
That means when you run the writer there is no one waiting for the data you write and you get the error.
You need to run the read and the writer in opposite order: First the writer so it writes to the pipe, and then the reader to read the data from the pipe.

Related

Cygwin - Blocking on opening a named fifo causes another thread to block on opening a regular file

A blocked open of a named pipe in Cygwin causes another thread to hang when it tries to open any file, including a simple text file. The below code reproduces the issue on cygwin 3.1.6(0.340/5/3), and works fine (does not hang) on RHEL 7.
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <thread>
#include <sys/stat.h>
#include <fcntl.h>
void openFile() {
int fd;
printf("inside new thread\n");
sleep(10); // Ensure main thread reaches call to open()
printf("opening a simple file\n");
if((fd = open("simpleFile", 0600)) == -1) { // simpleFile is a simple text file in the filesystem
printf("failed opening a simple file\n");
}
printf("simple file opened successfully\n");
close(fd);
printf("simple file closed\n");
}
int main(int argc, char *argv[]) {
int fd;
char readBuffer[PIPE_BUF];
printf("creating named pipe\n");
if (mkfifo("namedPipe", 0600)) {
printf("creating named pipe failed\n");
}
printf("creating thread\n");
std::thread pipeCreator = std::thread(openFile);
printf("opening named pipe for read\n");
fd = open("namedPipe", O_RDONLY); // Block will only release when we echo something into namedPipe
printf("reading from named pipe\n");
if (read(fd, readBuffer, PIPE_BUF) == -1) {
printf("error reading from pipe\n");
}
printf("read successfully from named pipe\n");
pipeCreator.join();
return 0;
}
Running this prints:
creating named pipe
creating thread
opening named pipe for read
inside new thread
opening a simple file
And then blocks until the other side of the namedPipe is opened.
Once freed it writes the rest of the prints:
reading from named pipe
simple file opened successfully
read successfully from named pipe
simple file closed
On RHEL this prints the expected result:
creating named pipe
creating thread
opening named pipe for read
inside new thread
opening a simple file
simple file opened successfully
simple file closed
And only then the main thread hangs until something is echoed into namedPipe.
We're working on a workaround which won't block, but that involves busy waiting which isn't great.
Can anyone explain this behavior?
On Cygwin the open syscall locks the file descriptor table for the entire duration of the syscall. Which means all open syscalls are essentially sequentialized.
See syscalls.cc/open():
extern "C" int
open (const char *unix_path, int flags, ...)
{
. . .
cygheap_fdnew fd; // <-- here
And cygheap.h:
class cygheap_fdnew : public cygheap_fdmanip
{
public:
cygheap_fdnew (int seed_fd = -1, bool lockit = true)
{
if (lockit)
cygheap->fdtab.lock (); // <-- here
. . .
I see no easy way around this, but I guess it should be possible to unlock the fd table once a descriptor has been created at least in case of a fifo (see fhandler_fifo), since a fifo blocks on open. You can discuss this further on cygwin-developers.

Creating non blocking pipes to child that does not block and can be reused

I am trying to create a inter process communication bus using pipes.
I can send messages to the client, and i can receive messages at the client.
I also tried to create another pipe which goes the other way, child-> parent.
However I need this communication to be non blocking and I want to send messages in both directions with some undefined time gap in between.
It appears i can not send more then one message, I take it it is due to the fclose(); closing the stream, however if i remove the close, the program stops working...
How can I make this code nonblocking two way parent -> child communication through pipes?
Later I want to connect a child-binary using exec(), and connecting this binary's stdin, stdout to my parent, so that I can pass messages to the stdin of the child and retrieve answers through the "childParent" descriptor.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define READ_SIDE 0
#define WRITE_SIDE 1
/* Read characters from the pipe and echo them to stdout. */
void
read_from_pipe (int file)
{
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
}
/* Write some random text to the pipe. */
void
write_to_pipe (int file, char * message)
{
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, message);
//fprintf (stream, "goodbye, world!\n");
//Dont forget to close
fclose (stream);
}
void end(){
//kill process and close pipes
}
int
main (void)
{
pid_t pid;
int parentToChild[2];
int childToParent[2];
/* Create the pipes. */
if (pipe (parentToChild))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
if (pipe (childToParent))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
/* Create the child process. */
pid = fork ();
if (pid == (pid_t) 0)
{
/* This is the child process.
Close other end first. */
close(childToParent[READ_SIDE]);
close (parentToChild[WRITE_SIDE]);
read_from_pipe (parentToChild[READ_SIDE]);
write_to_pipe(childToParent[WRITE_SIDE], "Child sent message to parent");
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
/* The fork failed. */
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
/* This is the parent process.
Close other end first. */
close(childToParent[WRITE_SIDE]);
close (parentToChild[READ_SIDE]);
write_to_pipe (parentToChild[WRITE_SIDE],"Parent sent message to child");
read_from_pipe(childToParent[READ_SIDE]);
//Send more messages...
return EXIT_SUCCESS;
}
}
UPDATE
It appears that sometimes the communication only happens one way, depending on which process gets to read/write first I guess.
There are several issues to be considered. First, pipes have a finite
maximum length (4096 was common in the distant past); any write to a
pipe which has more data in it than that will block, as will any read
from an empty pipe. These are fundamental to the way pipes work, so
when you speak of non-blocking, you have to take them into consideration
(or use asynchronous IO).
Second, if you really need to control things at this level, you might
want to consider using Posix level IO, rather than streams. If you do
use streams (either iostream or FILE*), then you have to take into
account the buffering they use. In particular, when you want to be sure
that the data is output to the pipe, you need to flush (fflush on
the FILE*). With regards to sending more than one message, and the
code not working without the fclose, replacing the fclose with
fflush should be all you need to fix this.
And while I'm at it: your use of fprintf for output is extremely
dangerous. If you're getting a message from an external source, and
(possibly) don't know what it contains, you should use fputs to output
it, or possibly something like fprintf( fd, "%s\n", message ) (if you
want to append a new line). As you've done it, if the message contains
a '%', strange things will happen. More generally, you should prefer
the much safer iostream, but for simple things like this, it doesn't
matter much. And for what you're actually doing, Posix level IO is
probably just as appropriate, or more so. With Posix level IO, you
don't get any formatting or buffering: but since you're not using the
formatting capabilities, and the buffering it part of your problem...

Communication between pipes in linux

I have two functions writer() and reader(). I am writing message into the pipe from writer() function and reading it from the reader() function. The problem I am facing is that message is being written in the pipe, but it's not getting read. Maybe there is problem in opening pipe for reading. The code is:
#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;
//edit
int fifo = mkfifo("/tmp/mypipe", S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
void writer()
{
char message[] = "this is a message";
int fd;
fd = open("pipe" , O_WRONLY);
write(fd , message , sizeof(message));
cout<<"message wrote: "<<message<<"\n"; // gives output
} // message wrote: this is a message
void reader()
{
char buffer[100];
int fd;
fd = open("pipe" , O_RDONLY);
read(fd , buffer , 100);
cout<<"message is: "<<buffer<<"\n"; // gives output
} // message is:
int main()
{
writer();
reader();
return 0;
}
I've debugged it, and I think the problem is, fifo is not being created correctly. I don't know how to resolve this. Need more help.
Thank you for any help.
My guess is that you have not created the pipe in a correct way. Take a look at the mkfifo man page. For the umask value take a look at the umask man page.
something like mkfifo("/tmp/pipe", 0666), before you open /tmp/pipe in the reader/writer.
Also take a look at the fifo man page:
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So your problem now is, that the open(..., O_WRONLY) blocks until the reader opens the file.
To try it out, let just the reader run and then use echo "test" > /tmp/pipe.
Update:
Or use threads, i just tried it out.
int main() {
mkfifo(fifo_name.c_str(), 0666);
std::thread w(writer);
std::thread r(reader);
w.join();
r.join();
unlink(fifo_name.c_str());
return 0;
}
you also have to #include <thread>, add this compiler flag: -std=c++0x and add the following library to the linker: -lpthread.
Be sure to check returns from function calls, since they can tell you what the problem is.
Include errno.h:
#include <errno.h>
#include <string.h>
And check errno when you get an error return from your write or read open attempt:
fd = open("pipe" , O_WRONLY);
if (fd < 0)
{
cout << "writer open failed: " << errno << "(" << strerror(errno) << ")\n";
/* exit */
}
As another answer states, you're not using mkfifo(), so you're making a typical file (which would also work but may fail if you don't provide O_CREAT and a mode argument).
It is about how named pipe work in posix. You can only write in it, if there is already somebody, who is reading from it. If there is none, your write() operation will be blocked until somebody don't read.
The simplest solution were, if
You used nonblocking I/O
You implemented the reader and the writer in different processes (threads) and called the reader before the writer.

Redirecting subprocess output to FIFO not working

I'm forking a process and running mysqldump with execl. I want to redirect the output of mysqldump to FIFO I created. But opening of fifo is failing and so dup2().
int main(int argc, char** argv) {
int i;
char *fifoname="/home/maverick/myfifo";
mkfifo(fifoname,0666);
int forkret=fork();
if(forkret==0){
setuid(getpwnam("mysql")->pw_uid);
cout<<"In child....Running as :"<<(int)getuid()<<endl;
sleep(2);
int fdw=open(fifoname,O_WRONLY);
if ((dup2(fdw, STDOUT_FILENO)) != STDOUT_FILENO)
cout<<"Error redirecting output of mysqldump ";
if (dup2(fdw, STDERR_FILENO) != STDERR_FILENO)
cout<<"Error redirecting error stream of mysqldump";
execl("mysqldump","-u","root","-proot","--all-databases");
}
else{
char buf[20];
int fdr=open(fifoname,O_RDONLY);
while(read(fdr,(char*)buf,sizeof(buf))!=0){
cout<<buf;
}
}
return 0;
}
The open () call is failing..I can't understand what is wrong here..
You are creating the fifo allowing access only to the user and group that owns it, and then using setuid to change user. Presumably, the new user does not have permission to access the file.
You need to open the file before calling setuid.
I use two different files instead of dup2. In the first file I open for writing in the parent and reading in the child. The second I open to the writing in the son and reading in the father.
In this question I show a little of how I do
FIFO - Restore communication in C ++

popen simultaneous read and write [duplicate]

This question already has answers here:
Can popen() make bidirectional pipes like pipe() + fork()?
(6 answers)
Closed 3 years ago.
Is it possible to read and write to a file descriptor returned by popen. I have an interactive process I'd like to control through C. If this isn't possible with popen, is there any way around it?
As already answered, popen works in one direction. If you need to read and write, You can create a pipe with pipe(), span a new process by fork() and exec functions and then redirect its input and outputs with dup2(). Anyway I prefer exec over popen, as it gives you better control over the process (e.g. you know its pid)
EDITED:
As comments suggested, a pipe can be used in one direction only. Therefore you have to create separate pipes for reading and writing. Since the example posted before was wrong, I deleted it and created a new, correct one:
#include<unistd.h>
#include<sys/wait.h>
#include<sys/prctl.h>
#include<signal.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main(int argc, char** argv)
{
pid_t pid = 0;
int inpipefd[2];
int outpipefd[2];
char buf[256];
char msg[256];
int status;
pipe(inpipefd);
pipe(outpipefd);
pid = fork();
if (pid == 0)
{
// Child
dup2(outpipefd[0], STDIN_FILENO);
dup2(inpipefd[1], STDOUT_FILENO);
dup2(inpipefd[1], STDERR_FILENO);
//ask kernel to deliver SIGTERM in case the parent dies
prctl(PR_SET_PDEATHSIG, SIGTERM);
//replace tee with your process
execl("/usr/bin/tee", "tee", (char*) NULL);
// Nothing below this line should be executed by child process. If so,
// it means that the execl function wasn't successfull, so lets exit:
exit(1);
}
// The code below will be executed only by parent. You can write and read
// from the child using pipefd descriptors, and you can send signals to
// the process using its pid by kill() function. If the child process will
// exit unexpectedly, the parent process will obtain SIGCHLD signal that
// can be handled (e.g. you can respawn the child process).
//close unused pipe ends
close(outpipefd[0]);
close(inpipefd[1]);
// Now, you can write to outpipefd[1] and read from inpipefd[0] :
while(1)
{
printf("Enter message to send\n");
scanf("%s", msg);
if(strcmp(msg, "exit") == 0) break;
write(outpipefd[1], msg, strlen(msg));
read(inpipefd[0], buf, 256);
printf("Received answer: %s\n", buf);
}
kill(pid, SIGKILL); //send SIGKILL signal to the child process
waitpid(pid, &status, 0);
}
The reason popen() and friends don't offer bidirectional communication is that it would be deadlock-prone, due to buffering in the subprocess. All the makeshift pipework and socketpair() solutions discussed in the answers suffer from the same problem.
Under UNIX, most commands cannot be trusted to read one line and immediately process it and print it, except if their standard output is a tty. The reason is that stdio buffers output in userspace by default, and defers the write() system call until either the buffer is full or the stdio stream is closed (typically because the program or script is about to exit after having seen EOF on input). If you write to such a program's stdin through a pipe, and now wait for an answer from that program's stdout (without closing the ingress pipe), the answer is stuck in the stdio buffers and will never come out - This is a deadlock.
You can trick some line-oriented programs (eg grep) into not buffering by using a pseudo-tty to talk to them; take a look at libexpect(3). But in the general case, you would have to re-run a different subprocess for each message, allowing to use EOF to signal the end of each message and cause whatever buffers in the command (or pipeline of commands) to be flushed. Obviously not a good thing performance-wise.
See more info about this problem in the perlipc man page (it's for bi-directional pipes in Perl but the buffering considerations apply regardless of the language used for the main program).
You want something often called popen2. Here's a basic implementation without error checking (found by a web search, not my code):
// http://media.unpythonic.net/emergent-files/01108826729/popen2.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "popen2.h"
int popen2(const char *cmdline, struct popen2 *childinfo) {
pid_t p;
int pipe_stdin[2], pipe_stdout[2];
if(pipe(pipe_stdin)) return -1;
if(pipe(pipe_stdout)) return -1;
//printf("pipe_stdin[0] = %d, pipe_stdin[1] = %d\n", pipe_stdin[0], pipe_stdin[1]);
//printf("pipe_stdout[0] = %d, pipe_stdout[1] = %d\n", pipe_stdout[0], pipe_stdout[1]);
p = fork();
if(p < 0) return p; /* Fork failed */
if(p == 0) { /* child */
close(pipe_stdin[1]);
dup2(pipe_stdin[0], 0);
close(pipe_stdout[0]);
dup2(pipe_stdout[1], 1);
execl("/bin/sh", "sh", "-c", cmdline, NULL);
perror("execl"); exit(99);
}
childinfo->child_pid = p;
childinfo->to_child = pipe_stdin[1];
childinfo->from_child = pipe_stdout[0];
close(pipe_stdin[0]);
close(pipe_stdout[1]);
return 0;
}
//#define TESTING
#ifdef TESTING
int main(void) {
char buf[1000];
struct popen2 kid;
popen2("tr a-z A-Z", &kid);
write(kid.to_child, "testing\n", 8);
close(kid.to_child);
memset(buf, 0, 1000);
read(kid.from_child, buf, 1000);
printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0));
printf("from child: %s", buf);
printf("waitpid() -> %d\n", waitpid(kid.child_pid, NULL, 0));
printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0));
return 0;
}
#endif
popen() can only open the pipe in read or write mode, not both. Take a look at this thread for a workaround.
In one of netresolve backends I'm talking to a script and therefore I need to write to its stdin and read from its stdout. The following function executes a command with stdin and stdout redirected to a pipe. You can use it and adapt it to your liking.
static bool
start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
{
int p1[2], p2[2];
if (!pid || !infd || !outfd)
return false;
if (pipe(p1) == -1)
goto err_pipe1;
if (pipe(p2) == -1)
goto err_pipe2;
if ((*pid = fork()) == -1)
goto err_fork;
if (*pid) {
/* Parent process. */
*infd = p1[1];
*outfd = p2[0];
close(p1[0]);
close(p2[1]);
return true;
} else {
/* Child process. */
dup2(p1[0], 0);
dup2(p2[1], 1);
close(p1[0]);
close(p1[1]);
close(p2[0]);
close(p2[1]);
execvp(*command, command);
/* Error occured. */
fprintf(stderr, "error running %s: %s", *command, strerror(errno));
abort();
}
err_fork:
close(p2[1]);
close(p2[0]);
err_pipe2:
close(p1[1]);
close(p1[0]);
err_pipe1:
return false;
}
https://github.com/crossdistro/netresolve/blob/master/backends/exec.c#L46
(I used the same code in Can popen() make bidirectional pipes like pipe() + fork()?)
Use forkpty (it's non-standard, but the API is very nice, and you can always drop in your own implementation if you don't have it) and exec the program you want to communicate with in the child process.
Alternatively, if tty semantics aren't to your liking, you could write something like forkpty but using two pipes, one for each direction of communication, or using socketpair to communicate with the external program over a unix socket.
You can't use popen to use two-way pipes.
In fact, some OSs don't support two-way pipes, in which case a socket-pair (socketpair) is the only way to do it.
popen works for me in both directions (read and write)
I have been using a popen() pipe in both directions..
Reading and writing a child process stdin and stdout with the file descriptor returned by popen(command,"w")
It seems to work fine..
I assumed it would work before I knew better, and it does.
According posts above this shouldn't work.. which worries me a little bit.
gcc on raspbian (raspbery pi debian)