Thread: Problem with O_NONBLOCK Pipe

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    61

    Question Problem with O_NONBLOCK Pipe

    Hi,
    I'm trying to send and receive using pipes:

    send.cpp
    Code:
    struct
        {
                long a;
                long b;
        }T;
    cout << "1" << endl;
    if ( access ( FIFO_NAME, F_OK ) == -1 ) {
                res = mkfifo ( FIFO_NAME, 0755 );
                if ( res != 0 )
                        cout << " Can't make fifo" << endl;
    }
    
    cout << "2" << endl;
    pipe_fd = open ( FIFO_NAME, O_WRONLY);
    cout << "3: " << pipe_fd << endl;
    a=b=1;
    res = write ( pipe_fd, &T, sizeof ( T ) );
    cout << "4" << endl;
    close(pipe_fd);
    recv.cpp
    Code:
    cout << "1" << endl;
    pipe_fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK);
    cout << "2" << endl;
    res = read(pipe_fd, &T, sizeof(T));
    cout << T.a << T.b << endl;
    close(pipe_fd);
    Code:
    ./send
    ./recv
    open is correct, but when send.cpp executes "write" the program terminates and "4" is not displayed!!!! I recv side the T.a and T.b are not correct !

    What's wrong with my programs?! (I have to say that programs are working correct when I remove O_NONBLOCK falg)

    thanks

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    What is the pipe_fd that is printed out in the sender?
    bit∙hub [bit-huhb] n. A source and destination for information.

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    pipe_fd is an int var as file descriptor. I've used it in write function.

  4. #4
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    That wasn't my question...
    Code:
    cout << "3: " << pipe_fd << endl;
    What is the output of that line of code.
    bit∙hub [bit-huhb] n. A source and destination for information.

  5. #5
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    ou, sorry! It changes in every execution but Is not -1

  6. #6
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    Unknown problem? No one has used O_NONBLOCK before?!!!!

  7. #7
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Well you are probably getting a SIGPIPE sent to your application due to writing before the receiver has opened its side of the pipe.

    From the documentation:
    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
    .
    Since you are opening the pipe as non-blocking, that bolded part does not happen for you. This is why it works when you don't use O_NONBLOCK, but it doesn't work for you now.
    bit∙hub [bit-huhb] n. A source and destination for information.

  8. #8
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    Thanks, I know this, But how can I use pipes in nonblocking mode? I couldn't find any example

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Do you need to use nonblocking mode? What problem are you trying to solve?
    bit∙hub [bit-huhb] n. A source and destination for information.

  10. #10
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    If you are in non-blocking mode you'll have to poll the device (or use select()) to see when data is there (and that would be in a loop).

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    Thanks, would you mind give me an example or use select in the program I wrote in the first post?

  12. #12
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    Code:
    int main(void)
    {
            int file, retval;
            char buf[1024];
    
            if ((file = open("something", O_NONBLOCK)) < 0){
                    return -EFAULT;
            }
            while (1){
                    retval = read(fd, buf, 1023);
                    if (retval < 0){
                            break;
                    }
                    if (retval){
                            buf[retval] = '\0';
                            printf("Got data: len = %i, data = %s\n", retval, buf);
                    }
                    if (!strcmp(buf, "STOPLOOP")){
                            break;
                    }
            }
            if (retval < 0){
                    printf("Got an error: %i\n", retval);
                    if (errno){
                            perror("read");
                    }
            }
            close(fd);
            return retval;
    }
    Quote Originally Posted by man select
    SELECT(2) Linux Programmer's Manual SELECT(2)

    NAME
    select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O multiplexing

    SYNOPSIS
    /* According to POSIX.1-2001 */
    #include <sys/select.h>

    /* According to earlier standards */
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    int select(int nfds, fd_set *readfds, fd_set *writefds,
    fd_set *exceptfds, struct timeval *timeout);

    void FD_CLR(int fd, fd_set *set);
    int FD_ISSET(int fd, fd_set *set);
    void FD_SET(int fd, fd_set *set);
    void FD_ZERO(fd_set *set);

    #include <sys/select.h>

    int pselect(int nfds, fd_set *readfds, fd_set *writefds,
    fd_set *exceptfds, const struct timespec *timeout,
    const sigset_t *sigmask);

    Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

    pselect(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

    DESCRIPTION
    select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors
    become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to
    perform the corresponding I/O operation (e.g., read(2)) without blocking.

    The operation of select() and pselect() is identical, with three differences:

    (i) select() uses a timeout that is a struct timeval (with seconds and microseconds), while pselect() uses a struct timespec
    (with seconds and nanoseconds).

    (ii) select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.

    (iii) select() has no sigmask argument, and behaves as pselect() called with NULL sigmask.

    Three independent sets of file descriptors are watched. Those listed in readfds will be watched to see if characters become avail-
    able for reading (more precisely, to see if a read will not block; in particular, a file descriptor is also ready on end-of-file),
    those in writefds will be watched to see if a write will not block, and those in exceptfds will be watched for exceptions. On exit,
    the sets are modified in place to indicate which file descriptors actually changed status. Each of the three file descriptor sets
    may be specified as NULL if no file descriptors are to be watched for the corresponding class of events.

    Four macros are provided to manipulate the sets. FD_ZERO() clears a set. FD_SET() and FD_CLR() respectively add and remove a given
    file descriptor from a set. FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.

    nfds is the highest-numbered file descriptor in any of the three sets, plus 1.

    timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval stucture are zero,
    then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.

    sigmask is a pointer to a signal mask (see sigprocmask(2)); if it is not NULL, then pselect() first replaces the current signal mask
    by the one pointed to by sigmask, then does the "select" function, and then restores the original signal mask.

    Other than the difference in the precision of the timeout argument, the following pselect() call:

    ready = pselect(nfds, &readfds, &writefds, &exceptfds,
    timeout, &sigmask);

    is equivalent to atomically executing the following calls:

    sigset_t origmask;

    sigprocmask(SIG_SETMASK, &sigmask, &origmask);
    ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
    sigprocmask(SIG_SETMASK, &origmask, NULL);

    The reason that pselect() is needed is that if one wants to wait for either a signal or for a file descriptor to become ready, then
    an atomic test is needed to prevent race conditions. (Suppose the signal handler sets a global flag and returns. Then a test of
    this global flag followed by a call of select() could hang indefinitely if the signal arrived just after the test but just before
    the call. By contrast, pselect() allows one to first block signals, handle the signals that have come in, then call pselect() with
    the desired sigmask, avoiding the race.)

    The timeout
    The time structures involved are defined in <sys/time.h> and look like

    struct timeval {
    long tv_sec; /* seconds */
    long tv_usec; /* microseconds */
    };

    and

    struct timespec {
    long tv_sec; /* seconds */
    long tv_nsec; /* nanoseconds */
    };

    (However, see below on the POSIX.1-2001 versions.)

    Some code calls select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portable way to sleep with subsec-
    ond precision.

    On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this.
    (POSIX.1-2001 permits either behavior.) This causes problems both when Linux code which reads timeout is ported to other operating
    systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it.
    Consider timeout to be undefined after select() returns.

    RETURN VALUE
    On success, select() and pselect() return the number of file descriptors contained in the three returned descriptor sets (that is,
    the total number of bits that are set in readfds, writefds, exceptfds) which may be zero if the timeout expires before anything
    interesting happens. On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not
    rely on their contents after an error.

    ERRORS
    EBADF An invalid file descriptor was given in one of the sets. (Perhaps a file descriptor that was already closed, or one on which
    an error has occurred.)

    EINTR A signal was caught; see signal(7).

    EINVAL nfds is negative or the value contained within timeout is invalid.

    ENOMEM unable to allocate memory for internal tables.

  13. #13
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    Thanks a lot, I'm gonna test it and I will report the result here

  14. #14
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    I wrote the program to 'write' on the read program you wrote. But some times the write program fails on write and read program sometimes crashes on open or read. Also, you haven't used 'select' function !!!

  15. #15
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    I'm going to be disappointed
    But I think using a blocking read after successful nonblocking read will do my job!

    Another question: After closing my program, will the pipe file be deleted? I think no. So why?

    Thanks anyone

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pipe(): Interprocess or Intraprocess comm?
    By @nthony in forum C Programming
    Replies: 2
    Last Post: 03-28-2007, 07:27 PM
  2. Pipe problem, popen(), pipe().
    By apacz in forum C Programming
    Replies: 7
    Last Post: 06-08-2006, 12:55 AM
  3. named pipe problem
    By fnoyan in forum Linux Programming
    Replies: 0
    Last Post: 05-28-2006, 05:54 AM
  4. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  5. beginner problem
    By The_Nymph in forum C Programming
    Replies: 4
    Last Post: 03-05-2002, 05:46 PM

Tags for this Thread