Skip to content

fcntl(O_NONBLOCK) does not work on a named pipe #159

@komh

Description

@komh

Hi/2.

As a title, fcntl(O_NONBLOCK) does not work on a named pipe.

Here is the test code.

#define INCL_DOS
#include <os2.h>

#include <stdio.h>
#include <io.h>
#include <fcntl.h>

#define PIPE_NAME "\\PIPE\\FCNTL\\NAMED_PIPE"

static int named_pipe( int *ph )
{
    HPIPE hpipe;
    HFILE hpipeWrite;
    ULONG ulAction;

    DosCreateNPipe( PIPE_NAME,
                    &hpipe,
                    NP_ACCESS_DUPLEX,
                    NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1,
                    32768, 32768, 0 );

    DosConnectNPipe( hpipe );

    DosOpen( PIPE_NAME, &hpipeWrite, &ulAction, 0, FILE_NORMAL,
             OPEN_ACTION_OPEN_IF_EXISTS,
             OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_WRITEONLY,
             NULL );

    ph[ 0 ] = hpipe;
    ph[ 1 ] = hpipeWrite;

    return 0;

}

int check( const char *msg, int fd )
{
    ULONG ulState;
    int fl;
    int failed;
    ULONG rc;

    rc = DosQueryNPHState( fd, &ulState );
    if(!rc)
    {
        fl = fcntl(fd, F_GETFL);

        rc = fl != -1 ? 0 : 1;
    }

    failed = rc ||
             ((( ulState & NP_NOWAIT ) == NP_NOWAIT ) !=
              (( fl & O_NONBLOCK ) == O_NONBLOCK ));

    printf("%s: %s, fcntl() = %s(%s)\n",
           failed ? "FAILED" : "PASSED", msg,
           ( fl & O_NONBLOCK ) ? "Non-block" : "Block",
           ( ulState & NP_NOWAIT ) ? "Non-block" : "Block");

    return failed;
}

int main( void )
{
    int ph[ 2 ];
    int fd;
    int fl;
    int errors = 0;

    printf("Testing fcntl(O_NONBLOCK) for a named pipe\n");

    named_pipe( ph );

    fd = ph[ 0 ];
    fl = fcntl( fd, F_GETFL );
    errors += check("S: Import", fd );

    fcntl( fd, F_SETFL, fl & ~O_NONBLOCK );
    errors += check("S: Set to BLOCK", fd );

    fcntl( fd, F_SETFL, fl | O_NONBLOCK );
    errors += check("S: Set to NON-BLOCK", fd );

    fd = ph[ 1 ];
    fl = fcntl( fd, F_GETFL );
    errors += check("C: Import", fd );

    fcntl( fd, F_SETFL, fl & ~O_NONBLOCK );
    errors += check("C: Set to BLOCK", fd );

    fcntl( fd, F_SETFL, fl | O_NONBLOCK );
    errors += check("C: Set to NON-BLOCK", fd );

    close( ph[ 0 ]);
    close( ph[ 1 ]);

    return !!errors;
}

And I attach the patch.

0001-filehandles-support-O_NONBLOCK-for-a-named-pipe.patch

From c39ae307a1cc08f93b24bc085e1363248a98f650 Mon Sep 17 00:00:00 2001
From: KO Myung-Hun <[email protected]>
Date: Tue, 7 Oct 2014 17:13:05 +0900
Subject: [PATCH] filehandles: support O_NONBLOCK for a named pipe

---
 src/emx/src/lib/sys/filehandles.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/src/emx/src/lib/sys/filehandles.c b/src/emx/src/lib/sys/filehandles.c
index 2b8a9cc..9c6a154 100644
--- a/src/emx/src/lib/sys/filehandles.c
+++ b/src/emx/src/lib/sys/filehandles.c
@@ -1347,6 +1347,12 @@ static __LIBC_PFH fhGet(int fh)
             if (!_fmode_bin)
                 fLibc |= O_TEXT;
 
+            /*
+             * Blocking flag for a named pipe.
+             */
+            if (!DosQueryNPHState((HFILE)fh, &fulMode) && (fulMode & NP_NOWAIT))
+                fLibc |= O_NONBLOCK;
+
 
             /*
              * Allocate a new handle for this filehandle.
@@ -1461,6 +1467,23 @@ int __libc_FHSetFlags(__LIBC_PFH pFH, int fh, unsigned fFlags)
             rc = DosSetFHState(fh, fulNewState);
         }
     }
+    if (!rc && !DosQueryNPHState(fh, &fulState))
+    {
+        ULONG fulNewState;
+        LIBC_ASSERTM(     ((fulState & NP_NOWAIT) != 0 )
+                      ==  ((pFH->fFlags & O_NONBLOCK) != 0),
+                     "Nowait flags are out of sync for file hFile %d (%#x)! fulState=%08lx fFlags=%08x\n",
+                     fh, fh, fulState, pFH->fFlags);
+        if (fFlags & O_NONBLOCK)
+            fulNewState = fulState | NP_NOWAIT;
+        else
+            fulNewState = fulState & ~NP_NOWAIT;
+        if (fulNewState != fulState)
+        {
+            fulNewState &= NP_NOWAIT | NP_READMODE_MESSAGE; /* Turn off non-participating bits. */
+            rc = DosSetNPHState(fh, fulNewState);
+        }
+    }
     FS_RESTORE();
 
     if (!rc)
-- 
2.50.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions