error writing with FIFO's the terminal just hangs no output - linux

i am trying to read and write between two processes using FIFOs but when i open a FIFO it doesnt print any message that i have given it to print similarly when I write to it it aslo doesnt display anything ...so how am I suppose to know if its working or not? why does it hang in the terminal it just keeps taking input and doesnt end?please help me out here I think the code is correct but here it goes
int main ()
{
int fd;
char buffer[MAX];
char * os;
if(mkfifo("oss",0666)<0)
{
perror("FIFO (named pipe) could not be created.");
exit(-1);
}
else printf("\nPipe has been created...");
fd=open ("oss", O_WRONLY);
if (fd <0)
{
perror("Could not open named pipe.");
exit(-1);
}
else printf("Pipe has been opened.");
strcpy(buffer,"please connect :( ");
if( write (fd,buffer, strlen(buffer)+1) < 0 )
{
perror("Error writing to named Pipe (FIFO)");
exit(-1);
}
else
printf("Message has been written to pipe.");
i am using g++ on linux

The most important thing to know about FIFOs is that the open() syscall blocks until someone attempts to open the same FIFO for the other direction.
You cannot open a FIFO for writing, write something in it and close it and later open it for reading and retrieve the data. It has to be opened for reading and writing simultaneously, because it's a named PIPE.
Your program is probably hanging at line
fd=open ("oss", O_WRONLY);
as it's waiting for someone to open the FIFO for reading.
I learned this when writing a daemon controlled by commands written into a FIFO. I spent a day totally baffled and then read
man 2 open
which gave a hint to
man 7 fifo
where I found the solution.

Related

Need to close linux FIFO on the read side after each message

Here is what I did, and it works:
"server" side (reader) pseudocode
mkfifo()
while (true){
open()
select(...NULL)
while (select... timeval(0)) {
read()
}
close()
}
"client" side (writer) real C code
int fd;
char * myfifo = "/tmp/saveterm.fifo";
char *msg = "MESSAGE";
fd = open(myfifo, O_WRONLY);
write(fd, msg, strlen(msg));
close(fd);
Now you see I need to open/close the fifo on the server after each event read. Is this supposed to be so? At first I only opened it once before the loop, but after the first message, the 'select' call would never block again until closed and reopened, and was always returning 1 and ISSET for the descriptor.
Yes, it's supposed to be like this.
Named pipes behave the same way as anonymous pipes: they both represent a single stream that is terminated when the last writer closes it. Specifically, the reader is not meant to hang forever just in case some future program decides to open the pipe and continue writing.
If you want packet based communication through a file, how about using a Unix socket in datagram mode instead?

Interprocess Communication with pipe and file

i'm using linux as operating system and trying to communicate three processes with pipe and file. It should work with any file put on STDIN.
And pipe works just fine, but second process is unavailable to write one char into file properly or third to read.
Firstly of course i initialize function as semlock and semunlock and opening pipe is also there. I appreciate any help cause i have no clue.
if (!(PID[1] = fork ())) {
int BUF_SIZE = 4096;
char d[BUF_SIZE];
while (fgets (d, BUF_SIZE, stdin) != NULL) {
write (mypipe[1], &d, BUF_SIZE);
}
}
if (!(PID[2] = fork ())) {
int reading_size = 0;
char r;
close (mypipe[1]);
semlock (semid1);
while (reading_size = read (mypipe[0], &r, 1)) {
if ((file = fopen ("proces2.txt", "w")) == NULL) {
warn ("error !!!");
exit (1);
}
fputc (r, file);
fclose (file);
semunlock (semid2);
}
}
if (!(PID[3] = fork ())) {
char x;
semlock (semid2);
do {
if ((plikProces3 = fopen ("proces2.txt", "r")) == NULL) {
warn ("Blad przy otwarciu pliku do odczytu !!!");
exit (1);
}
i = getc (plikProces3);
o = fprintf (stdout, "%c", i);
fclose (plikProces3);
semunlock (semid1);
} while (i != EOF);
}
What makes you think the child runs first? You haven't waited for the child process to finish so can hit EOF reading the file, before the previous child has written. Shouldn't the last fork() call be a wait, so you know the file was written? As it stands you have 4 processes, NOT 3!!
Then you are closing the mypipe[1] in the 2nd child process which as it is a forked copy, does not close the pipe inthe first child. You also are trying to write BUFSIZ characters, so you appear to be trying to write out more characters than were written, try "write (mypipe[1], &d, strlen(d));".
It looks very odd, to have the fopen() & fclose() within the character read/write loop. You really want to re-open & re-write 1 character into the file over and over?
Similarly the process2 file seems to be re-opened so the first character within would be written again and again, if it's non-empty.
There are bound to be other bugs, but that should help you for now.

How to handle the Linux socket revents POLLERR, POLLHUP and POLLNVAL?

I'm wondering what should be done when poll set these bits? Close socket, ignore it or what?
A POLLHUP means the socket is no longer connected. In TCP, this means FIN has been received and sent.
A POLLERR means the socket got an asynchronous error. In TCP, this typically means a RST has been received or sent. If the file descriptor is not a socket, POLLERR might mean the device does not support polling.
For both of the conditions above, the socket file descriptor is still open, and has not yet been closed (but shutdown() may have already been called). A close() on the file descriptor will release resources that are still being reserved on behalf of the socket. In theory, it should be possible to reuse the socket immediately (e.g., with another connect() call).
A POLLNVAL means the socket file descriptor is not open. It would be an error to close() it.
It depend on the exact error nature. Use getsockopt() to see the problem:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Values: http://www.xinotes.net/notes/note/1793/
The easiest way is to assume that the socket is no longer usable in any case and close it.
POLLNVAL means that the file descriptor value is invalid. It usually indicates an error in your program, but you can rely on poll returning POLLNVAL if you've closed a file descriptor and you haven't opened any file since then that might have reused the descriptor.
POLLERR is similar to error events from select. It indicates that a read or write call would return an error condition (e.g. I/O error). This does not include out-of-band data which select signals via its errorfds mask but poll signals via POLLPRI.
POLLHUP basically means that what's at the other end of the connection has closed its end of the connection. POSIX describes it as
The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred.
This is clear enough for a terminal: the terminal has gone away (same event that generates a SIGHUP: the modem session has been terminated, the terminal emulator window has been closed, etc.). POLLHUP is never sent for a regular file. For pipes and sockets, it depends on the operating system. Linux sets POLLHUP when the program on the writing end of a pipe closes the pipe, and sets POLLIN|POLLHUP when the other end of a socket closed the socket, but POLLIN only for a socket shutdown. Recent *BSD set POLLIN|POLLUP when the writing end of a pipe closes the pipe, and the behavior for sockets is more variable.
Minimal FIFO example
Once you understand when those conditions happen, it should be easy to know what to do with them.
poll.c
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
GitHub upstream.
Compile with:
gcc -o poll.out -std=c99 poll.c
Usage:
sudo mknod -m 666 poll0.tmp p
./poll.out
On another shell:
printf a >poll0.tmp
POLLHUP
If you don't modify the source: ./poll.out outputs:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
So:
POLLIN happens when input becomes available
POLLHUP happens when the file is closed by the printf
close(pfd.fd); and pfd.fd *= -1; clean things up, and we stop receiving POLLHUP
poll hangs forever
This is the normal operation.
You could now repoen the FIFO to wait for the next open, or exit the loop if you are done.
POLLNAL
If you comment out pfd.fd *= -1;: ./poll.out prints:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
and loops forever.
So:
POLLIN and POLLHUP and close happened as before
since we didn't set pfd.fd to a negative number, poll keeps trying to use the fd that we closed
this keeps returning POLLNVAL forever
So we see that this shouldn't have happened, and indicates a bug in your code.
POLLERR
I don't know how to generate a POLLERR with FIFOs. Let me know if there is way. But it should be possible with file_operations of a device driver.
Tested in Ubuntu 14.04.

rapidly writing to a temp file and renaming it... is that a good idea?

I have a daemon / service on a linux box (Debian 6) that reads from a hardware device, does some calculations and then updates a file with some relevant values. This happens about 5 times per second.
Any process that is reading the file always sees nicely structured and recent values in the file.
Here is the relevant daemon code:
while(1)
{
int rename_ret;
char tmpname[] = "/var/something/readout.tmp";
char txtname[] = "/var/something/readout.txt";
FILE *f = fopen(tmpname, "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
# ... reading from hardware, some calculation ...
# then print to the tmp file:
fprintf(f, "%12.4f\n", CntVal1);
fprintf(f, "%12.4f\n", CntVal2);
fclose(f);
rename_ret = rename(tmpname, txtname);
if(rename_ret != 0)
{
printf("Error: unable to rename the file");
exit(1);
}
nanosleep((struct timespec[]){{0, 200000000}}, NULL); // 0.2 sec
}
This works fine, but it feels kind of... wronggg?
Note that this is not the device driver, but instead it reads from the driver and processes the values for other processes to read.
So my question is:
is this a bad idea?
what's the proper way to go about it? I like the idea to be able to "just read a file" and get fairly recent values...

using EOF for signaling on unnamed pipes

I have a test program that uses unnamed pipes created with pipe() to communicate between parent and child processes created with fork() on a Linux system.
Normally, when the sending process closes the write fd of the pipe, the receiving process returns from read() with a value of 0, indicating EOF.
However, it seems that if I stuff the pipe with a fairly large amount of data (maybe 100K bytes0 before the receiver starts reading, the receiver blocks after reading all the data in the pipe - even though the sender has closed it.
I have verified that the sending process has closed the pipe with lsof, and it seems pretty clear that the receiver is blocked.
Which leads to the question: is closing one end of the pipe a reliable way to let the receiver know that there is no more data?
If it is, and there are no conditions that can lead to a read() blocking on an empty, closed FIFO, there's something wrong with my code. If not, it means I need to find an alternate method of signalling the end of the data stream.
Resolution
I was pretty sure that the original assumption was correct, that closing a pipe causes an EOF at the reader side, this question was just a shot in the dark - thinking maybe there was some subtle pipe behavior I was overlooking. Nearly every example you ever see with pipes is a toy that sends a few bytes and exits. Things often work differently when you are no longer doing atomic operations.
In any case, I tried to simplify my code to flush out the problem and was successful in finding my problem. In pseudocode, I ended up doing something like this:
create pipe1
if ( !fork() ) {
close pipe1 write fd
do some stuff reading pipe1 until EOF
}
create pipe2
if ( !fork() ) {
close pipe2 write fd
do some stuff reading pipe2 until EOF
}
close pipe1 read fd
close pipe2 read fd
write data to pipe1
get completion response from child 1
close pipe1 write fd
write data to pipe2
get completion response from child 2
close pipe2 write fd
wait for children to exit
The child process reading pipe1 was hanging, but only when the amount of data in the pipe became substantial. This was occurring even though I had closed the pipe that child1 was reading.
A look at the source shows the problem. When I forked the second child process, it grabbed its own copy of the pipe1 file descriptors, which were left open. Even though only one process should be writing to the pipe, having it open in the second process kept it from going into an EOF state.
The problem didn't show up with small data sets, because child2 was finishing its business quickly, and exiting. But with larger data sets, child2 wasn't returning quickly, and I ended up with a deadlock.
read should return EOF when the writers have closed the write end.
Since you do a pipe and then a fork, both processes will have the write fd open. It could be that in the reader process you have forgotten to close the write portion of the pipe.
Caveat: It has been a long time since I programmed on Unix. So it might be inaccurate.
Here is some code from: http://www.cs.uml.edu/~fredm/courses/91.308/files/pipes.html. Look at the "close unused" comments below.
#include <stdio.h>
/* The index of the "read" end of the pipe */
#define READ 0
/* The index of the "write" end of the pipe */
#define WRITE 1
char *phrase = "Stuff this in your pipe and smoke it";
main () {
int fd[2], bytesRead;
char message [100]; /* Parent process message buffer */
pipe ( fd ); /*Create an unnamed pipe*/
if ( fork ( ) == 0 ) {
/* Child Writer */
close (fd[READ]); /* Close unused end*/
write (fd[WRITE], phrase, strlen ( phrase) +1); /* include NULL*/
close (fd[WRITE]); /* Close used end*/
printf("Child: Wrote '%s' to pipe!\n", phrase);
} else {
/* Parent Reader */
close (fd[WRITE]); /* Close unused end*/
bytesRead = read ( fd[READ], message, 100);
printf ( "Parent: Read %d bytes from pipe: %s\n", bytesRead, message);
close ( fd[READ]); /* Close used end */
}
}

Resources