]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-123797: Check for runtime availability of `ptsname_r` on macos (#123806)
authorsobolevn <mail@sobolevn.me>
Fri, 20 Sep 2024 06:30:27 +0000 (09:30 +0300)
committerGitHub <noreply@github.com>
Fri, 20 Sep 2024 06:30:27 +0000 (09:30 +0300)
Lib/test/test_posix.py
Misc/NEWS.d/next/macOS/2024-09-07-12-14-54.gh-issue-123797.yFDeug.rst [new file with mode: 0644]
Modules/posixmodule.c

index 659b9a5a73305da89f85a2cc5aef606f66f1b396..35016b83a477fc5c0589bbf6bc471c39d1adc67e 100644 (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):
diff --git a/Misc/NEWS.d/next/macOS/2024-09-07-12-14-54.gh-issue-123797.yFDeug.rst b/Misc/NEWS.d/next/macOS/2024-09-07-12-14-54.gh-issue-123797.yFDeug.rst
new file mode 100644 (file)
index 0000000..f126bd0
--- /dev/null
@@ -0,0 +1 @@
+Check for runtime availability of ``ptsname_r`` function on macos.
index 8b2c4bd35a8da74b9957615268ef8bf54c6b6937..86366c66c4655297ed5bfda410e585e45b9f7fb2 100644 (file)
 #  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, *)
 
 #    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
 #  endif
 
+#  ifdef HAVE_PTSNAME_R
+#    define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
+#  endif
+
 #endif
 
 #ifdef HAVE_FUTIMESAT
 #  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];
 
-    ret = ptsname_r(fd, name, sizeof(name));
+    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