(root)/
Python-3.12.0/
Modules/
_multiprocessing/
multiprocessing.c
       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  }