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