diff --git a/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst b/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst new file mode 100644 index 00000000000..05f29955072 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2022-07-25-08-59-35.gh-issue-95174.g8woUW.rst @@ -0,0 +1,2 @@ +Python now detects missing ``dup`` function in WASI and works around some +missing :mod:`errno`, :mod:`select`, and :mod:`socket` constants. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 1ce7d86204e..3847349e5f6 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -4685,6 +4685,8 @@ exit: return return_value; } +#if ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) + PyDoc_STRVAR(os_dup2__doc__, "dup2($module, /, fd, fd2, inheritable=True)\n" "--\n" @@ -4740,6 +4742,8 @@ exit: return return_value; } +#endif /* ((defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))) */ + #if defined(HAVE_LOCKF) PyDoc_STRVAR(os_lockf__doc__, @@ -9105,6 +9109,10 @@ exit: #define OS_TCSETPGRP_METHODDEF #endif /* !defined(OS_TCSETPGRP_METHODDEF) */ +#ifndef OS_DUP2_METHODDEF + #define OS_DUP2_METHODDEF +#endif /* !defined(OS_DUP2_METHODDEF) */ + #ifndef OS_LOCKF_METHODDEF #define OS_LOCKF_METHODDEF #endif /* !defined(OS_LOCKF_METHODDEF) */ @@ -9352,4 +9360,4 @@ exit: #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=bae15f09a1b3d2e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ff792e207a18392 input=a9049054013a1b77]*/ diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c index bf6766e0234..0516e736705 100644 --- a/Modules/errnomodule.c +++ b/Modules/errnomodule.c @@ -280,6 +280,10 @@ errno_exec(PyObject *module) #ifdef ENOANO add_errcode("ENOANO", ENOANO, "No anode"); #endif +#if defined(__wasi__) && !defined(ESHUTDOWN) + // WASI SDK 16 does not have ESHUTDOWN, shutdown results in EPIPE. + #define ESHUTDOWN EPIPE +#endif #ifdef ESHUTDOWN add_errcode("ESHUTDOWN", ESHUTDOWN, "Cannot send after transport endpoint shutdown"); #else diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 40229bce0f4..2e89e2fb1d6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9316,7 +9316,9 @@ os_dup_impl(PyObject *module, int fd) return _Py_dup(fd); } - +// dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). +// dup2.c provides working dup2() if and only if F_DUPFD is available. +#if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) /*[clinic input] os.dup2 -> int fd: int @@ -9416,6 +9418,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) return res; } +#endif #ifdef HAVE_LOCKF diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 5c36eaaedeb..4eea928a268 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -63,6 +63,11 @@ extern void bzero(void *, int); # define SOCKET int #endif +// WASI SDK 16 does not have POLLPRIO, define as no-op +#if defined(__wasi__) && !defined(POLLPRI) +# define POLLPRI 0 +#endif + typedef struct { PyObject *close; PyTypeObject *poll_Type; diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 9b4155e164f..5641613452b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7786,6 +7786,10 @@ PyInit__socket(void) PyModule_AddIntMacro(m, MSG_EOR); #endif #ifdef MSG_TRUNC + // workaround for https://github.com/WebAssembly/wasi-libc/issues/305 + #if defined(__wasi__) && !defined(__WASI_RIFLAGS_RECV_DATA_TRUNCATED) + # define __WASI_RIFLAGS_RECV_DATA_TRUNCATED 2 + #endif PyModule_AddIntMacro(m, MSG_TRUNC); #endif #ifdef MSG_CTRUNC diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 87d55fa07e5..1135a121fcf 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -678,6 +678,9 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ /* Define if you have the 'inet_pton' function. */ #define HAVE_INET_PTON 1 +/* Define to 1 if you have the `dup' function. */ +#define HAVE_DUP 1 + /* framework name */ #define _PYTHONFRAMEWORK "" diff --git a/Python/dup2.c b/Python/dup2.c index 7c6bbfce11d..a1df0492099 100644 --- a/Python/dup2.c +++ b/Python/dup2.c @@ -11,6 +11,7 @@ * Return fd2 if all went well; return BADEXIT otherwise. */ +#include #include #include @@ -20,12 +21,17 @@ int dup2(int fd1, int fd2) { if (fd1 != fd2) { +#ifdef F_DUPFD if (fcntl(fd1, F_GETFL) < 0) return BADEXIT; if (fcntl(fd2, F_GETFL) >= 0) close(fd2); if (fcntl(fd1, F_DUPFD, fd2) < 0) return BADEXIT; +#else + errno = ENOTSUP; + return BADEXIT; +#endif } return fd2; } diff --git a/Python/fileutils.c b/Python/fileutils.c index 7e5d01f6e63..fb1e5ef9a03 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -2366,7 +2366,7 @@ _Py_dup(int fd) return -1; } -#else +#elif HAVE_DUP Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH fd = dup(fd); @@ -2383,6 +2383,10 @@ _Py_dup(int fd) _Py_END_SUPPRESS_IPH return -1; } +#else + errno = ENOTSUP; + PyErr_SetFromErrno(PyExc_OSError); + return -1; #endif return fd; } diff --git a/configure b/configure index d607c5e5d37..be045f2da3c 100755 --- a/configure +++ b/configure @@ -15545,7 +15545,7 @@ fi # checks for library functions for ac_func in \ accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \ - copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ diff --git a/configure.ac b/configure.ac index c5924169e03..a952324f492 100644 --- a/configure.ac +++ b/configure.ac @@ -4653,7 +4653,7 @@ fi # checks for library functions AC_CHECK_FUNCS([ \ accept4 alarm bind_textdomain_codeset chmod chown clock close_range confstr \ - copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \ + copy_file_range ctermid dup dup3 execv explicit_bzero explicit_memset \ faccessat fchmod fchmodat fchown fchownat fdopendir fdwalk fexecve \ fork fork1 fpathconf fstatat ftime ftruncate futimens futimes futimesat \ gai_strerror getegid getentropy geteuid getgid getgrgid getgrgid_r \ diff --git a/pyconfig.h.in b/pyconfig.h.in index aa9fc559fa2..37f748393e7 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -278,6 +278,9 @@ /* Define to 1 if you have the `dlopen' function. */ #undef HAVE_DLOPEN +/* Define to 1 if you have the `dup' function. */ +#undef HAVE_DUP + /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2