Communication between pipes in linux - c++

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.

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.

How to set PTY (Pseudo Terminal) to NON-ECHOING Unix in C / C++ [duplicate]

On linux, I am opening a pseudo tty on the master side. While there is no client on the slave side, the pseudo tty seems to be echoing everything I am writing to him, which is not what I am expecting.
Consider the folowing code :
int main(int argc, char * argv[])
{
int ptyfd;
int rc; /* return code */
char readbuf[3];
ptyfd = open("/dev/ptmx", O_RDWR | O_NOCTTY);
die_on_error(ptyfd, "open ptmx");
/* unlock and print slave name */
rc = unlockpt(ptyfd);
die_on_error(rc, "unlockpt");
printf("Slave pts name : %s\n", ptsname(ptyfd));
write(ptyfd, "C", 1);
rc=read(ptyfd, readbuf, 1);
die_on_error(rc, "read");
printf("read returned %c\n",readbuf[0]);
return 0;
}
When I run this program, I would expect the read call to block, but instead it immediately returns and the readbuf content is C. How can I change this behaviour ? When the slave side is not opened, I would like the character written on the master side to either vanish or be fifoed for later reading by the slave side.
Is changing the master side attributes the right way to do it ?
I thought the master side was not a tty, but apparently it is, so you can call things like tcgettattr and tcsetattr, and suppress the echo.
None of the older answers provided the correct C code, so here it is:
struct termios tmios;
tcgetattr(ptfd, &tmios);
tmios.c_lflag &= ~(ECHO);
tcsetattr(ptfd, TCSANOW, &tmios);
You can use the blocking getch() call. Also getch() will not echo the content.

Why does select on a named pipe with no writers block indefinitely?

I call select with a single named pipe fd in read_fds. This named pipe has no writers and has only been opened in non-blocking, read only mode. I would expect that the select returns with the named pipe fd marked as ready to read, and that trying to read from the pipe returns 0:
From the manpage on read:
When attempting to read from an empty pipe or FIFO:
If no process has the pipe open for writing, read() shall return 0 to > indicate end-of-file.
However, select just blocks indefinitely. Why is this the case?
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdexcept>
#include <thread>
#include <iostream>
int main()
{
char buf[4096];
// Create a named pipe
auto err = mkfifo("/tmp/whatever",0666);
if(err) {
throw std::runtime_error(
std::string("Failed to create fifo ")+
strerror(errno));
}
std::thread reader_thread(
[&](){
auto fd = open("/tmp/whatever",O_RDONLY|O_NONBLOCK);
if(fd < 0) {
throw std::runtime_error("Failed to open fifo");
}
fd_set fds;
while(1) {
FD_ZERO(&fds);
FD_SET(fd,&fds);
std::cerr << "calling select" << std::endl;
auto retval = select(fd+1,&fds,nullptr,nullptr,nullptr);
if(retval < 0) {
std::runtime_error("Failed to call select");
}
if(FD_ISSET(fd,&fds)) {
auto read_bytes = read(fd,buf,4096);
std::cerr << "read " << read_bytes << std::endl;
if(read_bytes==0) {
break;
}
}
}
close(fd);
});
reader_thread.join();
return 0;
}
From the POSIX documentation fo select:
A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. (The function might return data, an end-of-file indication, or an error other than one indicating that it is blocked, and in each of these cases the descriptor shall be considered ready for reading.
...
If none of the selected descriptors are ready for the requested operation, the pselect() or select() function shall block until at least one of the requested operations becomes ready, until the timeout occurs, or until interrupted by a signal.
From the pipe(7) manpage (which is the underlying object of a FIFO):
If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read(2) from the pipe will see end-of-file (read(2) will return 0).
Mind the usage of present perfect tense! This implies the FIFO has to be opened on both sides fiorst, the closed on the writer side (for your application) to generate an EOF condition.
So, unless the fifo is eventually closed by the writer, why should select return? The setting for the (fifo-)file itself is irrelevant for good reason: It would introduce a race-condition between opening on both sides when using the most efficient method to read more than one byte at a time. That's the normal way for e.g. a command pipe: start the reader process and lateron the writer (which is typically a completely unrelated program when using a named pipe).
If you want select to return early, use the timeout argument. But normally, one uses a seperate thread which can be terminated by a signal (see the select man-page for more information).
As a sidenote: One nice thing about Linux/POSIX is that it does not really matter whether you use a FIFO or a file or your microphone driver.

Pipe Broken, FIFO file

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.

Check keyboard input without stopping flow of loop [duplicate]

How do you do nonblocking console IO on Linux/OS X in C?
I want to add an example:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
char buf[20];
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
sleep(4);
int numRead = read(0, buf, 4);
if (numRead > 0) {
printf("You said: %s", buf);
}
}
When you run this program you have 4 seconds to provide input to standard in. If no input found, it will not block and will simply return.
2 sample executions:
Korays-MacBook-Pro:~ koraytugay$ ./a.out
fda
You said: fda
Korays-MacBook-Pro:~ koraytugay$ ./a.out
Korays-MacBook-Pro:~ koraytugay$
Like Pete Kirkham, I found cc.byexamples.com, and it worked for me. Go there for a good explanation of the problem, as well as the ncurses version.
My code needed to take an initial command from standard input or a file, then watch for a cancel command while the initial command was processed. My code is C++, but you should be able to use scanf() and the rest where I use the C++ input function getline().
The meat is a function that checks if there is any input available:
#include <unistd.h>
#include <stdio.h>
#include <sys/select.h>
// cc.byexamples.com calls this int kbhit(), to mirror the Windows console
// function of the same name. Otherwise, the code is the same.
bool inputAvailable()
{
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
return (FD_ISSET(0, &fds));
}
This has to be called before any stdin input function When I used std::cin before using this function, it never returned true again. For example, main() has a loop that looks like this:
int main(int argc, char* argv[])
{
std::string initialCommand;
if (argc > 1) {
// Code to get the initial command from a file
} else {
while (!inputAvailable()) {
std::cout << "Waiting for input (Ctrl-C to cancel)..." << std::endl;
sleep(1);
}
std::getline(std::cin, initialCommand);
}
// Start a thread class instance 'jobThread' to run the command
// Start a thread class instance 'inputThread' to look for further commands
return 0;
}
In the input thread, new commands were added to a queue, which was periodically processed by the jobThread. The inputThread looked a little like this:
THREAD_RETURN inputThread()
{
while( !cancelled() ) {
if (inputAvailable()) {
std::string nextCommand;
getline(std::cin, nextCommand);
commandQueue.lock();
commandQueue.add(nextCommand);
commandQueue.unlock();
} else {
sleep(1);
}
}
return 0;
}
This function probably could have been in main(), but I'm working with an existing codebase, not against it.
For my system, there was no input available until a newline was sent, which was just what I wanted. If you want to read every character when typed, you need to turn off "canonical mode" on stdin. cc.byexamples.com has some suggestions which I haven't tried, but the rest worked, so it should work.
You don't, really. The TTY (console) is a pretty limited device, and you pretty much don't do non-blocking I/O. What you do when you see something that looks like non-blocking I/O, say in a curses/ncurses application, is called raw I/O. In raw I/O, there's no interpretation of the characters, no erase processing etc. Instead, you need to write your own code that checks for data while doing other things.
In modern C programs, you can simplify this another way, by putting the console I/O into a thread or lightweight process. Then the I/O can go on in the usual blocking fashion, but the data can be inserted into a queue to be processed on another thread.
Update
Here's a curses tutorial that covers it more.
I bookmarked "Non-blocking user input in loop without ncurses" earlier this month when I thought I might need non-blocking, non-buffered console input, but I didn't, so can't vouch for whether it works or not. For my use, I didn't care that it didn't get input until the user hit enter, so just used aio to read stdin.
Here's a related question using C++ -- Cross-platform (linux/Win32) nonblocking C++ IO on stdin/stdout/stderr
Another alternative to using ncurses or threads is to use GNU Readline, specifically the part of it that allows you to register callback functions. The pattern is then:
Use select() on STDIN (among any other descriptors)
When select() tells you that STDIN is ready to read from, call readline's rl_callback_read_char()
If the user has entered a complete line, rl_callback_read_char will call your callback. Otherwise it will return immediately and your other code can continue.
Let`s see how it done in one of Linux utilites. For example, perf/builtin-top.c sources (simplified):
static void *display_thread(void *arg)
{
struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
struct termios save;
set_term_quiet_input(&save);
while (!done) {
switch (poll(&stdin_poll, 1, delay_msecs)) {
...
}
}
tcsetattr(0, TCSAFLUSH, &save);
}
So, if you want to check if any data available, you can use poll() or select() like this:
#include <sys/poll.h>
...
struct pollfd pfd = { .fd = 0, .events = POLLIN };
while (...) {
if (poll(&pfd, 1, 0)>0) {
// data available, read it
}
...
}
In this case you will receive events not on each key, but on whole line, after [RETURN] key is pressed. It's because terminal operates in canonical mode (input stream is buffered, and buffer flushes when [RETURN] pressed):
In canonical input processing mode, terminal input is processed in
lines terminated by newline ('\n'), EOF, or EOL characters. No input
can be read until an entire line has been typed by the user, and the
read function (see Input and Output Primitives) returns at most a
single line of input, no matter how many bytes are requested.
If you want to read characters immediately, you can use noncanonical mode. Use tcsetattr() to switch:
#include <termios.h>
void set_term_quiet_input()
{
struct termios tc;
tcgetattr(0, &tc);
tc.c_lflag &= ~(ICANON | ECHO);
tc.c_cc[VMIN] = 0;
tc.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &tc);
}
Simple programm (link to playground):
#include <stdio.h>
#include <unistd.h>
#include <sys/poll.h>
#include <termios.h>
void set_term_quiet_input()
{
struct termios tc;
tcgetattr(0, &tc);
tc.c_lflag &= ~(ICANON | ECHO);
tc.c_cc[VMIN] = 0;
tc.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &tc);
}
int main() {
struct pollfd pfd = { .fd = 0, .events = POLLIN };
set_term_quiet_input();
while (1) {
if (poll(&pfd, 1, 0)>0) {
int c = getchar();
printf("Key pressed: %c \n", c);
if (c=='q') break;
}
usleep(1000); // Some work
}
}
Not entirely sure what you mean by 'console IO' -- are you reading from STDIN, or is this a console application that reads from some other source?
If you're reading from STDIN, you'll need to skip fread() and use read() and write(), with poll() or select() to keep the calls from blocking. You may be able to disable input buffering, which should cause fread to return an EOF, with setbuf(), but I've never tried it.