gh-123797: Check for runtime availability of `ptsname_r` on macos (#123806)

This commit is contained in:
sobolevn 2024-09-20 09:30:27 +03:00 committed by GitHub
parent aae126748f
commit 3e36e5aef1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 10 deletions

View File

@ -2142,6 +2142,13 @@ class TestPosixWeaklinking(unittest.TestCase):
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.stat("file", dir_fd=0)
def test_ptsname_r(self):
self._verify_available("HAVE_PTSNAME_R")
if self.mac_ver >= (10, 13, 4):
self.assertIn("HAVE_PTSNAME_R", posix._have_functions)
else:
self.assertNotIn("HAVE_PTSNAME_R", posix._have_functions)
def test_access(self):
self._verify_available("HAVE_FACCESSAT")
if self.mac_ver >= (10, 10):

View File

@ -0,0 +1 @@
Check for runtime availability of ``ptsname_r`` function on macos.

View File

@ -125,6 +125,7 @@
# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
# define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
@ -206,6 +207,10 @@
# define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
# endif
# ifdef HAVE_PTSNAME_R
# define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
# endif
#endif
#ifdef HAVE_FUTIMESAT
@ -231,6 +236,7 @@
# define HAVE_PWRITEV_RUNTIME 1
# define HAVE_MKFIFOAT_RUNTIME 1
# define HAVE_MKNODAT_RUNTIME 1
# define HAVE_PTSNAME_R_RUNTIME 1
#endif
@ -8635,6 +8641,19 @@ os_unlockpt_impl(PyObject *module, int fd)
#endif /* HAVE_UNLOCKPT */
#if defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R)
static PyObject *
py_ptsname(int fd)
{
// POSIX manpage: Upon failure, ptsname() shall return a null pointer
// and may set errno. Always initialize errno to avoid undefined behavior.
errno = 0;
char *name = ptsname(fd);
if (name == NULL) {
return posix_error();
}
return PyUnicode_DecodeFSDefault(name);
}
/*[clinic input]
os.ptsname
@ -8656,22 +8675,22 @@ os_ptsname_impl(PyObject *module, int fd)
int ret;
char name[MAXPATHLEN+1];
if (HAVE_PTSNAME_R_RUNTIME) {
ret = ptsname_r(fd, name, sizeof(name));
}
else {
// fallback to ptsname() if ptsname_r() is not available in runtime.
return py_ptsname(fd);
}
if (ret != 0) {
errno = ret;
return posix_error();
}
#else
char *name;
name = ptsname(fd);
/* POSIX manpage: Upon failure, ptsname() shall return a null pointer and may set errno.
*MAY* set errno? Hmm... */
if (name == NULL)
return posix_error();
#endif /* HAVE_PTSNAME_R */
return PyUnicode_DecodeFSDefault(name);
#else
return py_ptsname(fd);
#endif /* HAVE_PTSNAME_R */
}
#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
@ -17751,6 +17770,9 @@ PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
#endif
#ifdef HAVE_PTSNAME_R
PROBE(probe_ptsname_r, HAVE_PTSNAME_R_RUNTIME)
#endif
@ -17891,6 +17913,10 @@ static const struct have_function {
{ "HAVE_UTIMENSAT", probe_utimensat },
#endif
#ifdef HAVE_PTSNAME_R
{ "HAVE_PTSNAME_R", probe_ptsname_r },
#endif
#ifdef MS_WINDOWS
{ "MS_WINDOWS", NULL },
#endif