| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Extension module used by multiprocessing package | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * multiprocessing.c | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-04-30 12:13:55 +01:00
										 |  |  |  * Copyright (c) 2006-2008, R Oudkerk | 
					
						
							|  |  |  |  * Licensed to PSF under a Contributor Agreement. | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "multiprocessing.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Merged revisions 70908,70939,71009,71022,71036 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
  r70908 | jesse.noller | 2009-03-31 17:20:35 -0500 (Tue, 31 Mar 2009) | 1 line
  Issue 5619: Pass MS CRT debug flags into subprocesses
........
  r70939 | jesse.noller | 2009-03-31 22:45:50 -0500 (Tue, 31 Mar 2009) | 1 line
  Fix multiprocessing.event to match the new threading.Event API
........
  r71009 | jesse.noller | 2009-04-01 19:03:28 -0500 (Wed, 01 Apr 2009) | 1 line
  issue5545: Switch to Autoconf for multiprocessing; special thanks to Martin Lowis for help
........
  r71022 | jesse.noller | 2009-04-01 21:32:55 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3110: Additional protection for SEM_VALUE_MAX on platforms, thanks to Martin Loewis
........
  r71036 | jesse.noller | 2009-04-01 23:22:09 -0500 (Wed, 01 Apr 2009) | 1 line
  Issue 3551: Raise ValueError if the size causes ERROR_NO_SYSTEM_RESOURCES
........
											
										 
											2009-04-05 21:24:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Function which raises exceptions based on error codes | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2012-10-07 18:08:47 +01:00
										 |  |  | _PyMp_SetError(PyObject *Type, int num) | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     switch (num) { | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     case MP_STANDARD_ERROR: | 
					
						
							|  |  |  |         if (Type == NULL) | 
					
						
							| 
									
										
										
										
											2012-12-19 14:33:35 +02:00
										 |  |  |             Type = PyExc_OSError; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyErr_SetExcFromWindowsErr(Type, 0); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case MP_SOCKET_ERROR: | 
					
						
							|  |  |  |         if (Type == NULL) | 
					
						
							| 
									
										
										
										
											2012-12-19 14:33:35 +02:00
										 |  |  |             Type = PyExc_OSError; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         PyErr_SetExcFromWindowsErr(Type, WSAGetLastError()); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #else /* !MS_WINDOWS */
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     case MP_STANDARD_ERROR: | 
					
						
							|  |  |  |     case MP_SOCKET_ERROR: | 
					
						
							|  |  |  |         if (Type == NULL) | 
					
						
							|  |  |  |             Type = PyExc_OSError; | 
					
						
							|  |  |  |         PyErr_SetFromErrno(Type); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif /* !MS_WINDOWS */
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     case MP_MEMORY_ERROR: | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case MP_EXCEPTION_HAS_BEEN_SET: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         PyErr_Format(PyExc_RuntimeError, | 
					
						
							| 
									
										
										
										
											2013-05-15 18:06:56 +02:00
										 |  |  |                      "unknown error number %d", num); | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | multiprocessing_closesocket(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							|  |  |  |     ret = closesocket((SOCKET) handle); | 
					
						
							|  |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ret) | 
					
						
							|  |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); | 
					
						
							|  |  |  |     Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | multiprocessing_recv(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  |     int size, nread; | 
					
						
							|  |  |  |     PyObject *buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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_IOError, WSAGetLastError()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     _PyBytes_Resize(&buf, nread); | 
					
						
							|  |  |  |     return buf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | multiprocessing_send(PyObject *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     HANDLE handle; | 
					
						
							|  |  |  |     Py_buffer buf; | 
					
						
							| 
									
										
										
										
											2013-09-07 17:40:45 +01:00
										 |  |  |     int ret, length; | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-07 17:40:45 +01:00
										 |  |  |     length = (int)Py_MIN(buf.len, INT_MAX); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_BEGIN_ALLOW_THREADS | 
					
						
							| 
									
										
										
										
											2013-09-07 17:40:45 +01:00
										 |  |  |     ret = send((SOCKET) handle, buf.buf, length, 0); | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |     Py_END_ALLOW_THREADS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyBuffer_Release(&buf); | 
					
						
							|  |  |  |     if (ret < 0) | 
					
						
							|  |  |  |         return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); | 
					
						
							|  |  |  |     return PyLong_FromLong(ret); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Function table | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef module_methods[] = { | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  | #ifdef MS_WINDOWS
 | 
					
						
							|  |  |  |     {"closesocket", multiprocessing_closesocket, METH_VARARGS, ""}, | 
					
						
							|  |  |  |     {"recv", multiprocessing_recv, METH_VARARGS, ""}, | 
					
						
							|  |  |  |     {"send", multiprocessing_send, METH_VARARGS, ""}, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-05-07 21:13:50 +03:00
										 |  |  | #if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__)
 | 
					
						
							| 
									
										
										
										
											2013-08-14 15:35:41 +01:00
										 |  |  |     {"sem_unlink", _PyMp_sem_unlink, METH_VARARGS, ""}, | 
					
						
							| 
									
										
										
										
											2014-07-28 23:01:02 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     {NULL} | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyModuleDef multiprocessing_module = { | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  |     "_multiprocessing", | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     -1, | 
					
						
							|  |  |  |     module_methods, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL, | 
					
						
							|  |  |  |     NULL | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | PyMODINIT_FUNC | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | PyInit__multiprocessing(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-17 10:23:14 +01:00
										 |  |  |     PyObject *module, *temp, *value = NULL; | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Initialize module */ | 
					
						
							|  |  |  |     module = PyModule_Create(&multiprocessing_module); | 
					
						
							|  |  |  |     if (!module) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(MS_WINDOWS) ||                                              \
 | 
					
						
							| 
									
										
										
										
											2009-11-28 12:48:43 +00:00
										 |  |  |   (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) | 
					
						
							| 
									
										
										
										
											2012-10-07 18:08:47 +01:00
										 |  |  |     /* Add _PyMp_SemLock type to module */ | 
					
						
							|  |  |  |     if (PyType_Ready(&_PyMp_SemLockType) < 0) | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2012-10-07 18:08:47 +01:00
										 |  |  |     Py_INCREF(&_PyMp_SemLockType); | 
					
						
							| 
									
										
										
										
											2010-10-17 02:14:36 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |         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). */ | 
					
						
							|  |  |  |         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; | 
					
						
							| 
									
										
										
										
											2012-10-07 18:08:47 +01:00
										 |  |  |         PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", | 
					
						
							| 
									
										
										
										
											2010-10-17 02:14:36 +00:00
										 |  |  |                              py_sem_value_max); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-10-07 18:08:47 +01:00
										 |  |  |     PyModule_AddObject(module, "SemLock", (PyObject*)&_PyMp_SemLockType); | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     /* 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) {           \ | 
					
						
							| 
									
										
										
										
											2012-04-18 20:51:15 +02:00
										 |  |  |         Py_DECREF(temp); Py_DECREF(value); return NULL; }         \ | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     Py_DECREF(value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 12:48:43 +00:00
										 |  |  | #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ADD_FLAG(HAVE_SEM_OPEN); | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_SEM_TIMEDWAIT
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ADD_FLAG(HAVE_SEM_TIMEDWAIT); | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_BROKEN_SEM_GETVALUE
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef HAVE_BROKEN_SEM_UNLINK
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     if (PyModule_AddObject(module, "flags", temp) < 0) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |     return module; | 
					
						
							| 
									
										
										
										
											2008-06-13 19:28:21 +00:00
										 |  |  | } |