Skip to content

Commit 7dc71c4

Browse files
authored
bpo-42780: Fix set_inheritable() for O_PATH file descriptors on Linux (GH-24172)
1 parent e0e398e commit 7dc71c4

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
@@ -3881,6 +3881,33 @@ def test_set_inheritable_cloexec(self):
38813881
self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
38823882
0)
38833883

3884+
@unittest.skipUnless(hasattr(os, 'O_PATH'), "need os.O_PATH")
3885+
def test_get_set_inheritable_o_path(self):
3886+
fd = os.open(__file__, os.O_PATH)
3887+
self.addCleanup(os.close, fd)
3888+
self.assertEqual(os.get_inheritable(fd), False)
3889+
3890+
os.set_inheritable(fd, True)
3891+
self.assertEqual(os.get_inheritable(fd), True)
3892+
3893+
os.set_inheritable(fd, False)
3894+
self.assertEqual(os.get_inheritable(fd), False)
3895+
3896+
def test_get_set_inheritable_badf(self):
3897+
fd = os_helper.make_bad_fd()
3898+
3899+
with self.assertRaises(OSError) as ctx:
3900+
os.get_inheritable(fd)
3901+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3902+
3903+
with self.assertRaises(OSError) as ctx:
3904+
os.set_inheritable(fd, True)
3905+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3906+
3907+
with self.assertRaises(OSError) as ctx:
3908+
os.set_inheritable(fd, False)
3909+
self.assertEqual(ctx.exception.errno, errno.EBADF)
3910+
38843911
def test_open(self):
38853912
fd = os.open(__file__, os.O_RDONLY)
38863913
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
@@ -1234,6 +1234,13 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
12341234
return 0;
12351235
}
12361236

1237+
#ifdef __linux__
1238+
if (errno == EBADF) {
1239+
// On Linux, ioctl(FIOCLEX) will fail with EBADF for O_PATH file descriptors
1240+
// Fall through to the fcntl() path
1241+
}
1242+
else
1243+
#endif
12371244
if (errno != ENOTTY && errno != EACCES) {
12381245
if (raise)
12391246
PyErr_SetFromErrno(PyExc_OSError);

0 commit comments

Comments
 (0)