/* * Extension module used by multiprocessing package * * multiprocessing.c * * Copyright (c) 2006-2008, R Oudkerk * Licensed to PSF under a Contributor Agreement. */ #include "multiprocessing.h" /*[python input] class HANDLE_converter(CConverter): type = "HANDLE" format_unit = '"F_HANDLE"' [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=9fad6080b79ace91]*/ /*[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]*/ { int nread; PyObject *buf; buf = PyBytes_FromStringAndSize(NULL, size); if (!buf) return NULL; Py_BEGIN_ALLOW_THREADS nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0); Py_END_ALLOW_THREADS if (nread < 0) { Py_DECREF(buf); return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); } _PyBytes_Resize(&buf, nread); return buf; } /*[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) && !defined(__ANDROID__) _MULTIPROCESSING_SEM_UNLINK_METHODDEF #endif {NULL} }; /* * Initialize */ static struct PyModuleDef multiprocessing_module = { PyModuleDef_HEAD_INIT, "_multiprocessing", NULL, -1, module_methods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC PyInit__multiprocessing(void) { PyObject *module, *temp, *value = NULL; /* Initialize module */ module = PyModule_Create(&multiprocessing_module); if (!module) return NULL; #if defined(MS_WINDOWS) || \ (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) /* Add _PyMp_SemLock type to module */ if (PyType_Ready(&_PyMp_SemLockType) < 0) return NULL; Py_INCREF(&_PyMp_SemLockType); { 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 NULL; PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", py_sem_value_max); } PyModule_AddObject(module, "SemLock", (PyObject*)&_PyMp_SemLockType); #endif /* Add configuration macros */ temp = PyDict_New(); if (!temp) return NULL; #define ADD_FLAG(name) \ value = Py_BuildValue("i", name); \ if (value == NULL) { Py_DECREF(temp); return NULL; } \ if (PyDict_SetItemString(temp, #name, value) < 0) { \ Py_DECREF(temp); Py_DECREF(value); return NULL; } \ Py_DECREF(value) #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_AddObject(module, "flags", temp) < 0) return NULL; return module; }