| /* | |
| * Extension module used by multiprocessing package | |
| * | |
| * multiprocessing.c | |
| * | |
| * Copyright (c) 2006-2008, R Oudkerk | |
| * Licensed to PSF under a Contributor Agreement. | |
| */ | |
| #include "multiprocessing.h" | |
| /*[clinic input] | |
| module _multiprocessing | |
| [clinic start generated code]*/ | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=01e0745f380ac6e3]*/ | |
| #include "clinic/multiprocessing.c.h" | |
| /* | |
| * Function which raises exceptions based on error codes | |
| */ | |
| PyObject * | |
| _PyMp_SetError(PyObject *Type, int num) | |
| { | |
| switch (num) { | |
| #ifdef MS_WINDOWS | |
| case MP_STANDARD_ERROR: | |
| if (Type == NULL) | |
| Type = PyExc_OSError; | |
| PyErr_SetExcFromWindowsErr(Type, 0); | |
| break; | |
| case MP_SOCKET_ERROR: | |
| if (Type == NULL) | |
| Type = PyExc_OSError; | |
| PyErr_SetExcFromWindowsErr(Type, WSAGetLastError()); | |
| break; | |
| #else /* !MS_WINDOWS */ | |
| case MP_STANDARD_ERROR: | |
| case MP_SOCKET_ERROR: | |
| if (Type == NULL) | |
| Type = PyExc_OSError; | |
| PyErr_SetFromErrno(Type); | |
| break; | |
| #endif /* !MS_WINDOWS */ | |
| case MP_MEMORY_ERROR: | |
| PyErr_NoMemory(); | |
| break; | |
| case MP_EXCEPTION_HAS_BEEN_SET: | |
| break; | |
| default: | |
| PyErr_Format(PyExc_RuntimeError, | |
| "unknown error number %d", num); | |
| } | |
| return NULL; | |
| } | |
| #ifdef MS_WINDOWS | |
| /*[clinic input] | |
| _multiprocessing.closesocket | |
| handle: HANDLE | |
| / | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _multiprocessing_closesocket_impl(PyObject *module, HANDLE handle) | |
| /*[clinic end generated code: output=214f359f900966f4 input=8a20706dd386c6cc]*/ | |
| { | |
| int ret; | |
| Py_BEGIN_ALLOW_THREADS | |
| ret = closesocket((SOCKET) handle); | |
| Py_END_ALLOW_THREADS | |
| if (ret) | |
| return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); | |
| Py_RETURN_NONE; | |
| } | |
| /*[clinic input] | |
| _multiprocessing.recv | |
| handle: HANDLE | |
| size: int | |
| / | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size) | |
| /*[clinic end generated code: output=92322781ba9ff598 input=6a5b0834372cee5b]*/ | |
| { | |
| PyBytesWriter *writer = PyBytesWriter_Create(size); | |
| if (!writer) { | |
| return NULL; | |
| } | |
| char *buf = PyBytesWriter_GetData(writer); | |
| Py_ssize_t nread; | |
| Py_BEGIN_ALLOW_THREADS | |
| nread = recv((SOCKET) handle, buf, size, 0); | |
| Py_END_ALLOW_THREADS | |
| if (nread < 0) { | |
| PyBytesWriter_Discard(writer); | |
| return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); | |
| } | |
| return PyBytesWriter_FinishWithSize(writer, nread); | |
| } | |
| /*[clinic input] | |
| _multiprocessing.send | |
| handle: HANDLE | |
| buf: Py_buffer | |
| / | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf) | |
| /*[clinic end generated code: output=52d7df0519c596cb input=41dce742f98d2210]*/ | |
| { | |
| int ret, length; | |
| length = (int)Py_MIN(buf->len, INT_MAX); | |
| Py_BEGIN_ALLOW_THREADS | |
| ret = send((SOCKET) handle, buf->buf, length, 0); | |
| Py_END_ALLOW_THREADS | |
| if (ret < 0) | |
| return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); | |
| return PyLong_FromLong(ret); | |
| } | |
| #endif | |
| /*[clinic input] | |
| _multiprocessing.sem_unlink | |
| name: str | |
| / | |
| [clinic start generated code]*/ | |
| static PyObject * | |
| _multiprocessing_sem_unlink_impl(PyObject *module, const char *name) | |
| /*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/ | |
| { | |
| return _PyMp_sem_unlink(name); | |
| } | |
| /* | |
| * Function table | |
| */ | |
| static PyMethodDef module_methods[] = { | |
| #ifdef MS_WINDOWS | |
| _MULTIPROCESSING_CLOSESOCKET_METHODDEF | |
| _MULTIPROCESSING_RECV_METHODDEF | |
| _MULTIPROCESSING_SEND_METHODDEF | |
| #endif | |
| #if !defined(POSIX_SEMAPHORES_NOT_ENABLED) | |
| _MULTIPROCESSING_SEM_UNLINK_METHODDEF | |
| #endif | |
| {NULL} | |
| }; | |
| /* | |
| * Initialize | |
| */ | |
| static int | |
| multiprocessing_exec(PyObject *module) | |
| { | |
| #ifdef HAVE_MP_SEMAPHORE | |
| PyTypeObject *semlock_type = (PyTypeObject *)PyType_FromModuleAndSpec( | |
| module, &_PyMp_SemLockType_spec, NULL); | |
| if (semlock_type == NULL) { | |
| return -1; | |
| } | |
| int rc = PyModule_AddType(module, semlock_type); | |
| Py_DECREF(semlock_type); | |
| if (rc < 0) { | |
| return -1; | |
| } | |
| PyObject *py_sem_value_max; | |
| /* Some systems define SEM_VALUE_MAX as an unsigned value that | |
| * causes it to be negative when used as an int (NetBSD). | |
| * | |
| * Issue #28152: Use (0) instead of 0 to fix a warning on dead code | |
| * when using clang -Wunreachable-code. */ | |
| if ((int)(SEM_VALUE_MAX) < (0)) { | |
| py_sem_value_max = PyLong_FromLong(INT_MAX); | |
| } | |
| else { | |
| py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); | |
| } | |
| if (py_sem_value_max == NULL) { | |
| return -1; | |
| } | |
| if (PyDict_SetItemString(semlock_type->tp_dict, "SEM_VALUE_MAX", | |
| py_sem_value_max) < 0) { | |
| Py_DECREF(py_sem_value_max); | |
| return -1; | |
| } | |
| Py_DECREF(py_sem_value_max); | |
| #endif | |
| /* Add configuration macros */ | |
| PyObject *flags = PyDict_New(); | |
| if (!flags) { | |
| return -1; | |
| } | |
| #define ADD_FLAG(name) \ | |
| do { \ | |
| PyObject *value = PyLong_FromLong(name); \ | |
| if (value == NULL) { \ | |
| Py_DECREF(flags); \ | |
| return -1; \ | |
| } \ | |
| if (PyDict_SetItemString(flags, #name, value) < 0) { \ | |
| Py_DECREF(flags); \ | |
| Py_DECREF(value); \ | |
| return -1; \ | |
| } \ | |
| Py_DECREF(value); \ | |
| } while (0) | |
| #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) | |
| ADD_FLAG(HAVE_SEM_OPEN); | |
| #endif | |
| #ifdef HAVE_SEM_TIMEDWAIT | |
| ADD_FLAG(HAVE_SEM_TIMEDWAIT); | |
| #endif | |
| #ifdef HAVE_BROKEN_SEM_GETVALUE | |
| ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); | |
| #endif | |
| #ifdef HAVE_BROKEN_SEM_UNLINK | |
| ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); | |
| #endif | |
| if (PyModule_Add(module, "flags", flags) < 0) { | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| static PyModuleDef_Slot multiprocessing_slots[] = { | |
| _Py_ABI_SLOT, | |
| {Py_mod_exec, multiprocessing_exec}, | |
| {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, | |
| {Py_mod_gil, Py_MOD_GIL_NOT_USED}, | |
| {0, NULL} | |
| }; | |
| static struct PyModuleDef multiprocessing_module = { | |
| PyModuleDef_HEAD_INIT, | |
| .m_name = "_multiprocessing", | |
| .m_size = 0, | |
| .m_methods = module_methods, | |
| .m_slots = multiprocessing_slots, | |
| }; | |
| PyMODINIT_FUNC | |
| PyInit__multiprocessing(void) | |
| { | |
| return PyModuleDef_Init(&multiprocessing_module); | |
| } |