1/* 2 * Extension module used by multiprocessing package 3 * 4 * multiprocessing.c 5 * 6 * Copyright (c) 2006-2008, R Oudkerk 7 * Licensed to PSF under a Contributor Agreement. 8 */ 9 10#include "multiprocessing.h" 11 12/*[python input] 13class HANDLE_converter(CConverter): 14 type = "HANDLE" 15 format_unit = '"F_HANDLE"' 16 17[python start generated code]*/ 18/*[python end generated code: output=da39a3ee5e6b4b0d input=9fad6080b79ace91]*/ 19 20/*[clinic input] 21module _multiprocessing 22[clinic start generated code]*/ 23/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01e0745f380ac6e3]*/ 24 25#include "clinic/multiprocessing.c.h" 26 27/* 28 * Function which raises exceptions based on error codes 29 */ 30 31PyObject * 32_PyMp_SetError(PyObject *Type, int num) 33{ 34 switch (num) { 35#ifdef MS_WINDOWS 36 case MP_STANDARD_ERROR: 37 if (Type == NULL) 38 Type = PyExc_OSError; 39 PyErr_SetExcFromWindowsErr(Type, 0); 40 break; 41 case MP_SOCKET_ERROR: 42 if (Type == NULL) 43 Type = PyExc_OSError; 44 PyErr_SetExcFromWindowsErr(Type, WSAGetLastError()); 45 break; 46#else /* !MS_WINDOWS */ 47 case MP_STANDARD_ERROR: 48 case MP_SOCKET_ERROR: 49 if (Type == NULL) 50 Type = PyExc_OSError; 51 PyErr_SetFromErrno(Type); 52 break; 53#endif /* !MS_WINDOWS */ 54 case MP_MEMORY_ERROR: 55 PyErr_NoMemory(); 56 break; 57 case MP_EXCEPTION_HAS_BEEN_SET: 58 break; 59 default: 60 PyErr_Format(PyExc_RuntimeError, 61 "unknown error number %d", num); 62 } 63 return NULL; 64} 65 66#ifdef MS_WINDOWS 67/*[clinic input] 68_multiprocessing.closesocket 69 70 handle: HANDLE 71 / 72 73[clinic start generated code]*/ 74 75static PyObject * 76_multiprocessing_closesocket_impl(PyObject *module, HANDLE handle) 77/*[clinic end generated code: output=214f359f900966f4 input=8a20706dd386c6cc]*/ 78{ 79 int ret; 80 81 Py_BEGIN_ALLOW_THREADS 82 ret = closesocket((SOCKET) handle); 83 Py_END_ALLOW_THREADS 84 85 if (ret) 86 return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); 87 Py_RETURN_NONE; 88} 89 90/*[clinic input] 91_multiprocessing.recv 92 93 handle: HANDLE 94 size: int 95 / 96 97[clinic start generated code]*/ 98 99static PyObject * 100_multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size) 101/*[clinic end generated code: output=92322781ba9ff598 input=6a5b0834372cee5b]*/ 102{ 103 int nread; 104 PyObject *buf; 105 106 buf = PyBytes_FromStringAndSize(NULL, size); 107 if (!buf) 108 return NULL; 109 110 Py_BEGIN_ALLOW_THREADS 111 nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0); 112 Py_END_ALLOW_THREADS 113 114 if (nread < 0) { 115 Py_DECREF(buf); 116 return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); 117 } 118 _PyBytes_Resize(&buf, nread); 119 return buf; 120} 121 122/*[clinic input] 123_multiprocessing.send 124 125 handle: HANDLE 126 buf: Py_buffer 127 / 128 129[clinic start generated code]*/ 130 131static PyObject * 132_multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf) 133/*[clinic end generated code: output=52d7df0519c596cb input=41dce742f98d2210]*/ 134{ 135 int ret, length; 136 137 length = (int)Py_MIN(buf->len, INT_MAX); 138 139 Py_BEGIN_ALLOW_THREADS 140 ret = send((SOCKET) handle, buf->buf, length, 0); 141 Py_END_ALLOW_THREADS 142 143 if (ret < 0) 144 return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); 145 return PyLong_FromLong(ret); 146} 147 148#endif 149 150/*[clinic input] 151_multiprocessing.sem_unlink 152 153 name: str 154 / 155 156[clinic start generated code]*/ 157 158static PyObject * 159_multiprocessing_sem_unlink_impl(PyObject *module, const char *name) 160/*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/ 161{ 162 return _PyMp_sem_unlink(name); 163} 164 165/* 166 * Function table 167 */ 168 169static PyMethodDef module_methods[] = { 170#ifdef MS_WINDOWS 171 _MULTIPROCESSING_CLOSESOCKET_METHODDEF 172 _MULTIPROCESSING_RECV_METHODDEF 173 _MULTIPROCESSING_SEND_METHODDEF 174#endif 175#if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__) 176 _MULTIPROCESSING_SEM_UNLINK_METHODDEF 177#endif 178 {NULL} 179}; 180 181 182/* 183 * Initialize 184 */ 185 186static int 187multiprocessing_exec(PyObject *module) 188{ 189#ifdef HAVE_MP_SEMAPHORE 190 191 /* Add _PyMp_SemLock type to module */ 192 if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) { 193 return -1; 194 } 195 196 { 197 PyObject *py_sem_value_max; 198 /* Some systems define SEM_VALUE_MAX as an unsigned value that 199 * causes it to be negative when used as an int (NetBSD). 200 * 201 * Issue #28152: Use (0) instead of 0 to fix a warning on dead code 202 * when using clang -Wunreachable-code. */ 203 if ((int)(SEM_VALUE_MAX) < (0)) 204 py_sem_value_max = PyLong_FromLong(INT_MAX); 205 else 206 py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); 207 208 if (py_sem_value_max == NULL) { 209 return -1; 210 } 211 if (PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", 212 py_sem_value_max) < 0) { 213 Py_DECREF(py_sem_value_max); 214 return -1; 215 } 216 Py_DECREF(py_sem_value_max); 217 } 218 219#endif 220 221 /* Add configuration macros */ 222 PyObject *flags = PyDict_New(); 223 if (!flags) { 224 return -1; 225 } 226 227#define ADD_FLAG(name) \ 228 do { \ 229 PyObject *value = PyLong_FromLong(name); \ 230 if (value == NULL) { \ 231 Py_DECREF(flags); \ 232 return -1; \ 233 } \ 234 if (PyDict_SetItemString(flags, #name, value) < 0) { \ 235 Py_DECREF(flags); \ 236 Py_DECREF(value); \ 237 return -1; \ 238 } \ 239 Py_DECREF(value); \ 240 } while (0) 241 242#if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) 243 ADD_FLAG(HAVE_SEM_OPEN); 244#endif 245#ifdef HAVE_SEM_TIMEDWAIT 246 ADD_FLAG(HAVE_SEM_TIMEDWAIT); 247#endif 248#ifdef HAVE_BROKEN_SEM_GETVALUE 249 ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); 250#endif 251#ifdef HAVE_BROKEN_SEM_UNLINK 252 ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); 253#endif 254 255 if (PyModule_AddObject(module, "flags", flags) < 0) { 256 Py_DECREF(flags); 257 return -1; 258 } 259 260 return 0; 261} 262 263static PyModuleDef_Slot multiprocessing_slots[] = { 264 {Py_mod_exec, multiprocessing_exec}, 265 {0, NULL} 266}; 267 268static struct PyModuleDef multiprocessing_module = { 269 PyModuleDef_HEAD_INIT, 270 .m_name = "_multiprocessing", 271 .m_methods = module_methods, 272 .m_slots = multiprocessing_slots, 273}; 274 275PyMODINIT_FUNC 276PyInit__multiprocessing(void) 277{ 278 return PyModuleDef_Init(&multiprocessing_module); 279} 280