Skip to content

Commit 844ec0b

Browse files
authored
bpo-42780: Fix set_inheritable() for O_PATH file descriptors on Linux (GH-24172) (GH-24277)
(cherry picked from commit 7dc71c4)
1 parent ebb2f26 commit 844ec0b

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

Lib/test/test_os.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3513,6 +3513,33 @@ def test_set_inheritable_cloexec(self):
35133513
self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
35143514
0)
35153515

3516+
@unittest.skipUnless(hasattr(os, 'O_PATH'), "need os.O_PATH")
3517+
def test_get_set_inheritable_o_path(self):
3518+
fd = os.open(__file__, os.O_PATH)
3519+
self.addCleanup(os.close, fd)
3520+
self.assertEqual(os.get_inheritable(fd), False)
3521+
3522+
os.set_inheritable(fd, True)
3523+
self.assertEqual(os.get_inheritable(fd), True)
3524+
3525+
os.set_inheritable(fd, False)
3526+
self.assertEqual(os.get_inheritable(fd), False)
3527+
3528+
def test_get_set_inheritable_badf(self):
3529+
fd = support.make_bad_fd()
3530+
3531+
with self.assertRaises(OSError) as ctx:
3532+
os.get_inheritable(fd)
3533+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3534+
3535+
with self.assertRaises(OSError) as ctx:
3536+
os.set_inheritable(fd, True)
3537+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3538+
3539+
with self.assertRaises(OSError) as ctx:
3540+
os.set_inheritable(fd, False)
3541+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3542+
35163543
def test_open(self):
35173544
fd = os.open(__file__, os.O_RDONLY)
35183545
self.addCleanup(os.close, fd)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix os.set_inheritable() for O_PATH file descriptors on Linux.

Python/fileutils.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,13 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
11651165
return 0;
11661166
}
11671167

1168+
#ifdef __linux__
1169+
if (errno == EBADF) {
1170+
// On Linux, ioctl(FIOCLEX) will fail with EBADF for O_PATH file descriptors
1171+
// Fall through to the fcntl() path
1172+
}
1173+
else
1174+
#endif
11681175
if (errno != ENOTTY && errno != EACCES) {
11691176
if (raise)
11701177
PyErr_SetFromErrno(PyExc_OSError);

0 commit comments

Comments
 (0)