multiprocessing.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. #include "multiprocessing.h"
  10. /*[python input]
  11. class HANDLE_converter(CConverter):
  12. type = "HANDLE"
  13. format_unit = '"F_HANDLE"'
  14. def parse_arg(self, argname, displayname):
  15. return """
  16. {paramname} = PyLong_AsVoidPtr({argname});
  17. if (!{paramname} && PyErr_Occurred()) {{{{
  18. goto exit;
  19. }}}}
  20. """.format(argname=argname, paramname=self.parser_name)
  21. [python start generated code]*/
  22. /*[python end generated code: output=da39a3ee5e6b4b0d input=3e537d244034affb]*/
  23. /*[clinic input]
  24. module _multiprocessing
  25. [clinic start generated code]*/
  26. /*[clinic end generated code: output=da39a3ee5e6b4b0d input=01e0745f380ac6e3]*/
  27. #include "clinic/multiprocessing.c.h"
  28. /*
  29. * Function which raises exceptions based on error codes
  30. */
  31. PyObject *
  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. #ifdef MS_WINDOWS
  66. /*[clinic input]
  67. _multiprocessing.closesocket
  68. handle: HANDLE
  69. /
  70. [clinic start generated code]*/
  71. static PyObject *
  72. _multiprocessing_closesocket_impl(PyObject *module, HANDLE handle)
  73. /*[clinic end generated code: output=214f359f900966f4 input=8a20706dd386c6cc]*/
  74. {
  75. int ret;
  76. Py_BEGIN_ALLOW_THREADS
  77. ret = closesocket((SOCKET) handle);
  78. Py_END_ALLOW_THREADS
  79. if (ret)
  80. return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
  81. Py_RETURN_NONE;
  82. }
  83. /*[clinic input]
  84. _multiprocessing.recv
  85. handle: HANDLE
  86. size: int
  87. /
  88. [clinic start generated code]*/
  89. static PyObject *
  90. _multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size)
  91. /*[clinic end generated code: output=92322781ba9ff598 input=6a5b0834372cee5b]*/
  92. {
  93. int nread;
  94. PyObject *buf;
  95. buf = PyBytes_FromStringAndSize(NULL, size);
  96. if (!buf)
  97. return NULL;
  98. Py_BEGIN_ALLOW_THREADS
  99. nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0);
  100. Py_END_ALLOW_THREADS
  101. if (nread < 0) {
  102. Py_DECREF(buf);
  103. return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
  104. }
  105. _PyBytes_Resize(&buf, nread);
  106. return buf;
  107. }
  108. /*[clinic input]
  109. _multiprocessing.send
  110. handle: HANDLE
  111. buf: Py_buffer
  112. /
  113. [clinic start generated code]*/
  114. static PyObject *
  115. _multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf)
  116. /*[clinic end generated code: output=52d7df0519c596cb input=41dce742f98d2210]*/
  117. {
  118. int ret, length;
  119. length = (int)Py_MIN(buf->len, INT_MAX);
  120. Py_BEGIN_ALLOW_THREADS
  121. ret = send((SOCKET) handle, buf->buf, length, 0);
  122. Py_END_ALLOW_THREADS
  123. if (ret < 0)
  124. return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
  125. return PyLong_FromLong(ret);
  126. }
  127. #endif
  128. /*[clinic input]
  129. _multiprocessing.sem_unlink
  130. name: str
  131. /
  132. [clinic start generated code]*/
  133. static PyObject *
  134. _multiprocessing_sem_unlink_impl(PyObject *module, const char *name)
  135. /*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/
  136. {
  137. return _PyMp_sem_unlink(name);
  138. }
  139. /*
  140. * Function table
  141. */
  142. static PyMethodDef module_methods[] = {
  143. #ifdef MS_WINDOWS
  144. _MULTIPROCESSING_CLOSESOCKET_METHODDEF
  145. _MULTIPROCESSING_RECV_METHODDEF
  146. _MULTIPROCESSING_SEND_METHODDEF
  147. #endif
  148. #if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__)
  149. _MULTIPROCESSING_SEM_UNLINK_METHODDEF
  150. #endif
  151. {NULL}
  152. };
  153. /*
  154. * Initialize
  155. */
  156. static int
  157. multiprocessing_exec(PyObject *module)
  158. {
  159. #ifdef HAVE_MP_SEMAPHORE
  160. PyTypeObject *semlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(
  161. module, &_PyMp_SemLockType_spec, NULL);
  162. if (semlock_type == NULL) {
  163. return -1;
  164. }
  165. int rc = PyModule_AddType(module, semlock_type);
  166. Py_DECREF(semlock_type);
  167. if (rc < 0) {
  168. return -1;
  169. }
  170. PyObject *py_sem_value_max;
  171. /* Some systems define SEM_VALUE_MAX as an unsigned value that
  172. * causes it to be negative when used as an int (NetBSD).
  173. *
  174. * Issue #28152: Use (0) instead of 0 to fix a warning on dead code
  175. * when using clang -Wunreachable-code. */
  176. if ((int)(SEM_VALUE_MAX) < (0)) {
  177. py_sem_value_max = PyLong_FromLong(INT_MAX);
  178. }
  179. else {
  180. py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX);
  181. }
  182. if (py_sem_value_max == NULL) {
  183. return -1;
  184. }
  185. if (PyDict_SetItemString(semlock_type->tp_dict, "SEM_VALUE_MAX",
  186. py_sem_value_max) < 0) {
  187. Py_DECREF(py_sem_value_max);
  188. return -1;
  189. }
  190. Py_DECREF(py_sem_value_max);
  191. #endif
  192. /* Add configuration macros */
  193. PyObject *flags = PyDict_New();
  194. if (!flags) {
  195. return -1;
  196. }
  197. #define ADD_FLAG(name) \
  198. do { \
  199. PyObject *value = PyLong_FromLong(name); \
  200. if (value == NULL) { \
  201. Py_DECREF(flags); \
  202. return -1; \
  203. } \
  204. if (PyDict_SetItemString(flags, #name, value) < 0) { \
  205. Py_DECREF(flags); \
  206. Py_DECREF(value); \
  207. return -1; \
  208. } \
  209. Py_DECREF(value); \
  210. } while (0)
  211. #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)
  212. ADD_FLAG(HAVE_SEM_OPEN);
  213. #endif
  214. #ifdef HAVE_SEM_TIMEDWAIT
  215. ADD_FLAG(HAVE_SEM_TIMEDWAIT);
  216. #endif
  217. #ifdef HAVE_BROKEN_SEM_GETVALUE
  218. ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE);
  219. #endif
  220. #ifdef HAVE_BROKEN_SEM_UNLINK
  221. ADD_FLAG(HAVE_BROKEN_SEM_UNLINK);
  222. #endif
  223. if (PyModule_AddObject(module, "flags", flags) < 0) {
  224. Py_DECREF(flags);
  225. return -1;
  226. }
  227. return 0;
  228. }
  229. static PyModuleDef_Slot multiprocessing_slots[] = {
  230. {Py_mod_exec, multiprocessing_exec},
  231. {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
  232. {0, NULL}
  233. };
  234. static struct PyModuleDef multiprocessing_module = {
  235. PyModuleDef_HEAD_INIT,
  236. .m_name = "_multiprocessing",
  237. .m_size = 0,
  238. .m_methods = module_methods,
  239. .m_slots = multiprocessing_slots,
  240. };
  241. PyMODINIT_FUNC
  242. PyInit__multiprocessing(void)
  243. {
  244. return PyModuleDef_Init(&multiprocessing_module);
  245. }