Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Modules/_multiprocessing/multiprocessing.c
12 views
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
_PyMp_SetError(PyObject *Type, int num)
41
{
42
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
case MP_STANDARD_ERROR:
56
case MP_SOCKET_ERROR:
57
if (Type == NULL)
58
Type = PyExc_OSError;
59
PyErr_SetFromErrno(Type);
60
break;
61
#endif /* !MS_WINDOWS */
62
case MP_MEMORY_ERROR:
63
PyErr_NoMemory();
64
break;
65
case MP_EXCEPTION_HAS_BEEN_SET:
66
break;
67
default:
68
PyErr_Format(PyExc_RuntimeError,
69
"unknown error number %d", num);
70
}
71
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
_multiprocessing_sem_unlink_impl(PyObject *module, const char *name)
168
/*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/
169
{
170
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
multiprocessing_exec(PyObject *module)
196
{
197
#ifdef HAVE_MP_SEMAPHORE
198
199
PyTypeObject *semlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(
200
module, &_PyMp_SemLockType_spec, NULL);
201
202
if (semlock_type == NULL) {
203
return -1;
204
}
205
int rc = PyModule_AddType(module, semlock_type);
206
Py_DECREF(semlock_type);
207
if (rc < 0) {
208
return -1;
209
}
210
211
PyObject *py_sem_value_max;
212
/* Some systems define SEM_VALUE_MAX as an unsigned value that
213
* causes it to be negative when used as an int (NetBSD).
214
*
215
* Issue #28152: Use (0) instead of 0 to fix a warning on dead code
216
* when using clang -Wunreachable-code. */
217
if ((int)(SEM_VALUE_MAX) < (0)) {
218
py_sem_value_max = PyLong_FromLong(INT_MAX);
219
}
220
else {
221
py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX);
222
}
223
if (py_sem_value_max == NULL) {
224
return -1;
225
}
226
if (PyDict_SetItemString(semlock_type->tp_dict, "SEM_VALUE_MAX",
227
py_sem_value_max) < 0) {
228
Py_DECREF(py_sem_value_max);
229
return -1;
230
}
231
Py_DECREF(py_sem_value_max);
232
233
#endif
234
235
/* Add configuration macros */
236
PyObject *flags = PyDict_New();
237
if (!flags) {
238
return -1;
239
}
240
241
#define ADD_FLAG(name) \
242
do { \
243
PyObject *value = PyLong_FromLong(name); \
244
if (value == NULL) { \
245
Py_DECREF(flags); \
246
return -1; \
247
} \
248
if (PyDict_SetItemString(flags, #name, value) < 0) { \
249
Py_DECREF(flags); \
250
Py_DECREF(value); \
251
return -1; \
252
} \
253
Py_DECREF(value); \
254
} while (0)
255
256
#if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)
257
ADD_FLAG(HAVE_SEM_OPEN);
258
#endif
259
#ifdef HAVE_SEM_TIMEDWAIT
260
ADD_FLAG(HAVE_SEM_TIMEDWAIT);
261
#endif
262
#ifdef HAVE_BROKEN_SEM_GETVALUE
263
ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE);
264
#endif
265
#ifdef HAVE_BROKEN_SEM_UNLINK
266
ADD_FLAG(HAVE_BROKEN_SEM_UNLINK);
267
#endif
268
269
if (PyModule_AddObject(module, "flags", flags) < 0) {
270
Py_DECREF(flags);
271
return -1;
272
}
273
274
return 0;
275
}
276
277
static PyModuleDef_Slot multiprocessing_slots[] = {
278
{Py_mod_exec, multiprocessing_exec},
279
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
280
{0, NULL}
281
};
282
283
static struct PyModuleDef multiprocessing_module = {
284
PyModuleDef_HEAD_INIT,
285
.m_name = "_multiprocessing",
286
.m_size = 0,
287
.m_methods = module_methods,
288
.m_slots = multiprocessing_slots,
289
};
290
291
PyMODINIT_FUNC
292
PyInit__multiprocessing(void)
293
{
294
return PyModuleDef_Init(&multiprocessing_module);
295
}
296
297