NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/58929: POSIX.1-2024 compliance: posix_close, POSIX_CLOSE_RESTART



    Date:        Sat, 21 Dec 2024 22:07:19 +0000
    From:        Taylor R Campbell <riastradh%NetBSD.org@localhost>
    Message-ID:  <20241221220723.04ECB84E92%mail.netbsd.org@localhost>

  | Correction: Our current close() -- and probably all existing close()
  | implementations outside buggy proprietary Unix variants -- is not
  | compliant with POSIX.1-2024, because if some underlying I/O is
  | interrupted by a signal it can fail with EINTR even though the
  | descriptor is unconditionally closed.  That is now forbidden (emphasis
  | added):

Can it really?   I haven't looked at our implementation (kernel)
but it used to be the case that even if close() slept for some time,
(like waiting for tty output to drain) and a signal occurred, close()
would still return 0.

But if not, surely the simple change here is to make that happen, not
to work around it in libc - just have sys_close() never return EINTR.

We have to function correctly in this case anyway, as we do close the
fd, so another close(fd) will just return EBADF - so anything draining
still in the kernel output queues needs to be properly handled without
any more userland assistance.

kre
  |
  | > If close() is interrupted by a signal that is to be caught, then it
  | > is unspecified whether it returns -1 with errno set to [EINTR] and
  | > fildes _remaining open_, or returns -1 with errno set to
  | > [EINPROGRESS] and fildes being closed, or returns 0 to indicate
  | > successful completion[...]
  | > 
  | > RATIONALE
  | > 
  | > [...] Note that the standard requires that close() and posix_close()
  | > _must leave fildes open after [EINTR]_ (in the cases where [EINTR]
  | > is permitted)
  |
  | So, in order to deal with POSIX.1-2024 having addressed the problem of
  | its own failure to adequately specify semantics by breaking
  | compatibility with every major OS on the planet, it looks like we'll
  | have to do some symbol magic under _POSIX_C_SOURCE -- something like
  | this:
  |
  | /* include/unistd.h */
  |
  | #if (_POSIX_C_SOURCE >= 202408L) && !defined(_NETBSD_SOURCE)
  | int	close(int) __RENAME(__posixly_correct_close);
  | int	posix_close(int, int);
  | #define	POSIX_CLOSE_RESTART	0
  | #else
  | int	close(int);
  | #endif
  |
  | /* lib/libc/sys/posixly_correct_close.c */
  |
  | int
  | __posixly_correct_close(int d)
  | {
  | 	const int ret = close(d);
  |
  | 	if (ret == -1 && errno == EINTR)
  | 		errno = EINPROGRESS;
  |
  | 	return ret;
  | }
  |
  | int
  | posix_close(int d, int flag)
  | {
  | 	const int ret = __posixly_correct_close(d);
  |
  | 	_DIAGASSERT(ret == 0 || errno != EINTR);
  |
  | 	if (ret == 0 && flag != 0) {
  | 		errno = EINVAL;
  | 		ret = -1;
  | 	}
  | 	return ret;
  | }
  |
  | What a colossal waste of effort -- and attack surface for new bugs to
  | crawl onto -- to force everyone else to bend over backwards to
  | accommodate bugs in proprietary implementations of close().
  |




Home | Main Index | Thread Index | Old Index