Skip to content

pipe() doesn't create a blocking pipe #13214

@emaxx-google

Description

@emaxx-google

On Emscripten, when reading from a pipe created via pipe(), the read() call returns immediately with EAGAIN when there's no data in the pipe. This contradicts the standard behavior specified by POSIX:

  EAGAIN The file descriptor fd refers to a file other than a
         socket and has been marked nonblocking (O_NONBLOCK), and
         the read would block.  See open(2) for further details on
         the O_NONBLOCK flag.
  EAGAIN or EWOULDBLOCK
         The file descriptor fd refers to a socket and has been
         marked nonblocking (O_NONBLOCK), and the read would block.

https://man7.org/linux/man-pages/man2/read.2.html

  If a process attempts to read from an empty pipe, then read(2)
  will block until data is available. <...>
  Nonblocking I/O is possible by using the fcntl(2)
  F_SETFL operation to enable the O_NONBLOCK open file status flag.

https://man7.org/linux/man-pages/man7/pipe.7.html

Given that pipe() doesn't set the O_NONBLOCK flag, I believe the Emscripten's behavior with returning EAGAIN is wrong.

Sample program:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
  int pipefd[2];
  if (pipe(pipefd)) {
    perror("pipe() failed");
    exit(-1);
  }
  if (argc > 1) {
    char c = 0;
    if (write(pipefd[1], &c, 1) != 1) {
      perror("write() failed");
      exit(-1);
    }
  }
  char c;
  if (read(pipefd[0], &c, 1) != 1) {
    perror("read() failed");
    exit(-1);
  }
  exit(0);
}

This program, when run under Emscripten, fails with "Resource temporarily unavailable". When the same program is run on Linux using standard g++ and libc, it correctly blocks in read().
P.S. The program also demonstrates that, in case write() was previously called, the data is successfully read from it under Emscripten.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions