NetBSD-Bugs archive

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

kern/60765: closefrom(2) does not actually return EINTR



>Number:         60765
>Category:       kern
>Synopsis:       closefrom(2) does not actually return EINTR
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 22 13:05:00 +0000 2026
>Originator:     Taylor R Campbell
>Release:        current, 11, 10, ...
>Organization:
The CloseFD Interruption, Inc.
>Environment:
>Description:

	The man page says:

	> ERRORS
	>      closefrom() will fail if:
	>      ...
	>      [EINTR]            An interrupt was received.

	But closefrom(fd), which is just a wrapper fcntl(fd, F_CLOSEM),
	cannot actually return EINTR -- it can only return EBADF (if fd
	< 0) or 0:

    349 	case F_CLOSEM:
    350 		if (fd < 0)
    351 			return SET_ERROR(EBADF);
    352 		while ((i = fdp->fd_lastfile) >= fd) {
    353 			if (fd_getfile(i) == NULL) {
    354 				/* Another thread has updated. */
    355 				continue;
    356 			}
    357 			fd_close(i);
    358 		}
    359 		return 0;

	https://nxr.netbsd.org/xref/src/sys/kern/sys_descrip.c?r=1.54#349

	Suppose a file is open on an interruptible nfs mount, or a
	socket is open with SO_LINGER enabled so it will wait in close
	until all buffered output has been transmitted.  Suppose
	there's _multiple_ such cases.  Suppose the network is flakes
	out so one of these sleeps.  And suppose the user hits ^C
	during the first sleep.

	Here are two possible outcomes from the user's perspective:

	1. closefrom fails with EINTR, having closed only some but not
	   all of the descriptors.

	2. closefrom wakes on signal during the first fd, and then goes
	   to sleep again on the second fd, not letting the application
	   respond to interruption.

	Neither option is correct in general (that's why we have
	SA_RESTART), but the system currently allows only (2).

>How-To-Repeat:

	code inspectman

>Fix:

	Consider one of:

	(a) Loop on ERESTART but break on EINTR from fd_close.
	(b) Omit EINTR from possible outcomes in man page.




Home | Main Index | Thread Index | Old Index