C Board  

Go Back   C Board > Platform Specific Boards > Linux Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-12-2009, 10:52 AM   #1
Registered User
 
Join Date: Jun 2009
Posts: 2
select, named pipe and O_RDONLY

hello!
this little program get named fifo as arguments and print whatever someone will write into the pipes. Example:

Code:
mkfifo fifo1
mkfifo fifo2
./es1 fifo1 fifo2

cat > fifo1
write here and my program will print out the lines
i used a select to block onto the pipes. the strange thing is that, if i open the pipe in rdonly, and i write a char into the pipe (with cat, e.g.) and quit that program (ctrl+c on cat), select stucks and say that the named pipe is still ready for reading: so i continue to read 0 bytes from it (and cpu goes to 99%). but if i open the pipe in RDWR, select (and the whole program) goes normal (it will block if i quit cat). why?

thank you very much
alexfranci is offline   Reply With Quote
Old 06-12-2009, 12:17 PM   #2
Frequently Quite Prolix
 
dwks's Avatar
 
Join Date: Apr 2005
Location: Canada
Posts: 7,698
I'm far from an expert on this, but perhaps when you CTRL-C cat it doesn't close the pipe properly. What happens if you use CTRL-D to quit cat instead (which should result in normal exit)?

[edit] By the way, post your code here on CBoard. More people will be inclined to help that way, and the code won't disappear. Here it is for posterity's sake.
Code:
/* Scrivere un programma C che prese in input da riga comando il pathname 
 * di molteplici FIFO (almeno 1, numero imprecisato) metta in output tutt
 * o cio' che arriva da qualsiasi di esse. Il programma non deve usare fo
 * rk ma una chiamata a scelta fra select o poll.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <limits.h>

#define BUFFER PIPE_BUF

int max(int a[], int num_elements)
{
   int i, max = a[0];
   for (i=0; i<num_elements; i++)
   {
     if (a[i] > max)
     {
        max = a[i];
     }
   }
   return (max);
}


int main(int argc, char **argv)
{
    register int i;
    int* fifos;
    int ready_fd;
    int nfds;
    int buff_count,count;
    fd_set fdset,tmpset;
    char buff[BUFFER];
    struct stat buf_fstat;

//    buff = (char *)malloc(sizeof(char)*4096);

    if (argc==1) /* wrong usage of args*/
    {
        printf("Usage: ./a.out 1st-fifo-path [2nd-fifo-path] ... [n-fifo-path]\n");
        return(-1);
    }
    else /* right usage of args */
    {
        FD_ZERO(&fdset); /* clear the fd_set */
        fifos = (int*) malloc(sizeof(int) * (argc-1));

        for (i=0;i<argc-1;i++)
        {
            if ((fifos[i] = open(argv[i+1],O_RDWR|O_NONBLOCK))<0)
            {
                perror("open");
                return(-2);
            }
            else
            {
                if (fstat(fifos[i],&buf_fstat))
                    perror("fstat");
                else if (! S_ISFIFO(buf_fstat.st_mode))
                {
                        printf("%s is not a pipe. Aborting\n",argv[i+1]);
                        return(-2);
                }
                else
                    FD_SET(fifos[i],&fdset);
            }
        }

        nfds = max(fifos,(argc-1))+1;
        memcpy((void *) &tmpset,(void *) &fdset, sizeof(fd_set));

        while (1)
        {
            /* we will use timeout=NULL to block indefinitely */
            if ((ready_fd = select(nfds,&fdset,NULL,NULL,NULL))<0)
                perror("select");
            else
            {
                #ifdef DEBUG
                    printf("ready fd: %d\n",ready_fd);
                #endif
                for (i=0,count=0;count<ready_fd||i<=(argc-1);i++)
                {
                    if (FD_ISSET(fifos[i],&fdset))
                    {
                        count++;
                        #ifdef DEBUG
                            printf("fifo: %d\n",i);
                        #endif
                        if ((buff_count=read(fifos[i],&buff,BUFFER))<0) 
                            perror("read");
                        else
                        {
                            #ifdef DEBUG
                                printf("read %d bytes\n",buff_count);
                            #endif
                            if (write(STDOUT_FILENO, buff, sizeof(char) * (unsigned int) buff_count)<0)
                                perror("write");
                        }
                    }      
                }
                memcpy((void *) &fdset,(void *) &tmpset, sizeof(fd_set));
            }
        }
    }
}
[/edit]
__________________
dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell


Other boards: DaniWeb, TPS
Unofficial Wiki FAQ: cpwiki.sf.net

My website: http://dwks.theprogrammingsite.com/
Projects: codeform, xuni, atlantis, nort, etc.
dwks is offline   Reply With Quote
Old 06-12-2009, 01:06 PM   #3
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
Using O_NONBLOCK with select() is almost never the right thing to do. You want BLOCKING reads, and you are relying on select() to tell you when a read operation would NOT block. Remove O_NONBLOCK and see what happens.

I'm not at all surprised that select() immediately returns when O_NONBLOCK is set. It's somewhat of a mystery why it does something different when opening in O_RDWR. I imagine that you're simply seeing unspecified behavior, triggered by the weirdness of opening a read-only end of a pipe in read-write mode. Don't do that!
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 06-12-2009, 03:24 PM   #4
Registered User
 
Join Date: Sep 2004
Location: California
Posts: 3,020
Quote:
Using O_NONBLOCK with select() is almost never the right thing to do.
This may be true with files, but it's definitely not true with socket file descriptors.
bithub is offline   Reply With Quote
Old 06-12-2009, 04:15 PM   #5
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
Quote:
Originally Posted by bithub View Post
This may be true with files, but it's definitely not true with socket file descriptors.
True. The interface is stupid and broken.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 06-12-2009, 07:09 PM   #6
critical genius
 
MK27's Avatar
 
Join Date: Jul 2008
Location: SE Queens
Posts: 5,230
Quote:
Originally Posted by brewbuck View Post
True. The interface is stupid and broken.
Oh, now you tell us
__________________

"A man can't just sit around." -- Larry Walters
MK27 is offline   Reply With Quote
Old 06-14-2009, 04:30 AM   #7
Registered User
 
Join Date: Jun 2009
Posts: 2
Quote:
Originally Posted by brewbuck View Post
Using O_NONBLOCK with select() is almost never the right thing to do. You want BLOCKING reads, and you are relying on select() to tell you when a read operation would NOT block. Remove O_NONBLOCK and see what happens.
if i remove the O_NONBLOCK flag, open stucks waiting for fifo1 be ready.
alexfranci is offline   Reply With Quote
Old 06-14-2009, 04:10 PM   #8
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
Quote:
Originally Posted by MK27 View Post
Oh, now you tell us
It wasn't relevant. He's using pipes, not sockets.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 06-14-2009, 04:10 PM   #9
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
Quote:
Originally Posted by alexfranci View Post
if i remove the O_NONBLOCK flag, open stucks waiting for fifo1 be ready.
Sounds like the proper behavior to me.

You could open in nonblock mode, then use fcntl() to set it to blocking mode after that.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Reply

Tags
fifo, named, pipe, rdonly, select

Thread Tools
Display Modes

Forum Jump


All times are GMT -6. The time now is 03:59 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22