Subject: bug#12881: Assume at least POSIX.1-1988 for fcntl.h

From: Eli Zaretskii <[email-masked]>
Date: Wed, 14 Nov 2012 19:33:45 +0200

> Date: Tue, 13 Nov 2012 23:37:58 -0800
> From: Paul Eggert <[email-masked]>
> CC: Eli Zaretskii <[email-masked]>
> 
> On POSIXish hosts it's long been safe to assume at least
> POSIX.1-1988, as the pre-POSIX platforms died out long ago.
> Attached is a patch to simplify Emacs to assume this
> for <fcntl.h>.  I haven't tested this on Windows but have
> tried to make the Windows port work by renaming its O_NDELAY
> flag to O_NONBLOCK, as POSIX standardized the spelling of this
> flag to be O_NONBLOCK.  I'll CC: this patch to Eli to give
> him a heads-up.  This patch is relative to trunk bzr 110892.

Renaming O_NDELAY is a no-brainer, but the patch does much more than
just that.  In several places, it actually changes the code involved
in dealing with the related issues.  Here's one example:

> @@ -4847,23 +4795,8 @@
>  	      else if (nread == -1 && errno == EWOULDBLOCK)
>  		;
>  #endif
> -	      /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
> -		 and Emacs uses O_NONBLOCK, so what we get is EAGAIN.  */
> -#if O_NONBLOCK
> -	      else if (nread == -1 && errno == EAGAIN)
> -		;
> -#else
> -#if O_NDELAY
> -	      else if (nread == -1 && errno == EAGAIN)
> -		;
> -	      /* Note that we cannot distinguish between no input
> -		 available now and a closed pipe.
> -		 With luck, a closed pipe will be accompanied by
> -		 subprocess termination and SIGCHLD.  */
> -	      else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc))
> -		;
> -#endif /* O_NDELAY */
> -#endif /* O_NONBLOCK */
> +	      else if (nread == -1 && errno == EAGAIN)
> +		;

Here, the code that was left is identical to the one used by platforms
with O_NONBLOCK, but the code used by platforms with O_NDELAY was
different in non-trivial ways.

Another potential problem is that the Windows emulation of fcntl only
works for sockets, whereas O_NONBLOCK is now used in other system
calls, like in emacs_open etc.

This patch also modifies code unrelated to O_NONBLOCK, like this one:

> --- src/callproc.c	2012-11-14 04:55:41 +0000
> +++ src/callproc.c	2012-11-14 07:26:25 +0000
> @@ -1317,16 +1317,7 @@
>      return fd;
>    else
>      {
> -      int new;
> -#ifdef F_DUPFD
> -      new = fcntl (fd, F_DUPFD, minfd);
> -#else
> -      new = dup (fd);
> -      if (new != -1)
> -	/* Note that we hold the original FD open while we recurse,
> -	   to guarantee we'll get a new FD if we need it.  */
> -	new = relocate_fd (new, minfd);
> -#endif
> +      int new = fcntl (fd, F_DUPFD, minfd);
>        if (new == -1)
>  	{
>  	  const char *message_1 = "Error while setting up child: ";

Likewise with O_NOCTTY.

It's possible that you've already analyzed all these places, and they
either aren't getting compiled on Windows or are no-ops.  If so,
please tell the details.  Failing that, Someone(TM) will have to do
the footwork of making sure these changes don't break non-Posix
platforms.