Skip to content

Commit 6893523

Browse files
authored
bpo-42780: Fix set_inheritable() for O_PATH file descriptors on Linux (GH-24172) (GH-24278)
(cherry picked from commit 7dc71c4)
1 parent 0654c4c commit 6893523

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
@@ -3659,6 +3659,33 @@ def test_set_inheritable_cloexec(self):
36593659
self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
36603660
0)
36613661

3662+
@unittest.skipUnless(hasattr(os, 'O_PATH'), "need os.O_PATH")
3663+
def test_get_set_inheritable_o_path(self):
3664+
fd = os.open(__file__, os.O_PATH)
3665+
self.addCleanup(os.close, fd)
3666+
self.assertEqual(os.get_inheritable(fd), False)
3667+
3668+
os.set_inheritable(fd, True)
3669+
self.assertEqual(os.get_inheritable(fd), True)
3670+
3671+
os.set_inheritable(fd, False)
3672+
self.assertEqual(os.get_inheritable(fd), False)
3673+
3674+
def test_get_set_inheritable_badf(self):
3675+
fd = support.make_bad_fd()
3676+
3677+
with self.assertRaises(OSError) as ctx:
3678+
os.get_inheritable(fd)
3679+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3680+
3681+
with self.assertRaises(OSError) as ctx:
3682+
os.set_inheritable(fd, True)
3683+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3684+
3685+
with self.assertRaises(OSError) as ctx:
3686+
os.set_inheritable(fd, False)
3687+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3688+
36623689
def test_open(self):
36633690
fd = os.open(__file__, os.O_RDONLY)
36643691
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)