Changeset 391 for python/trunk/Modules/_multiprocessing/multiprocessing.c
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Modules/_multiprocessing/multiprocessing.c
r10 r391 9 9 #include "multiprocessing.h" 10 10 11 #if (defined(CMSG_LEN) && defined(SCM_RIGHTS)) 12 #define HAVE_FD_TRANSFER 1 13 #else 14 #define HAVE_FD_TRANSFER 0 15 #endif 16 11 17 PyObject *create_win32_namespace(void); 12 18 … … 21 27 mp_SetError(PyObject *Type, int num) 22 28 { 23 29 switch (num) { 24 30 #ifdef MS_WINDOWS 25 case MP_STANDARD_ERROR: 26 27 28 29 30 31 32 33 34 31 case MP_STANDARD_ERROR: 32 if (Type == NULL) 33 Type = PyExc_WindowsError; 34 PyErr_SetExcFromWindowsErr(Type, 0); 35 break; 36 case MP_SOCKET_ERROR: 37 if (Type == NULL) 38 Type = PyExc_WindowsError; 39 PyErr_SetExcFromWindowsErr(Type, WSAGetLastError()); 40 break; 35 41 #else /* !MS_WINDOWS */ 36 37 38 39 40 41 42 case MP_STANDARD_ERROR: 43 case MP_SOCKET_ERROR: 44 if (Type == NULL) 45 Type = PyExc_OSError; 46 PyErr_SetFromErrno(Type); 47 break; 42 48 #endif /* !MS_WINDOWS */ 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 "unkown error number %d", num);61 62 49 case MP_MEMORY_ERROR: 50 PyErr_NoMemory(); 51 break; 52 case MP_END_OF_FILE: 53 PyErr_SetNone(PyExc_EOFError); 54 break; 55 case MP_EARLY_END_OF_FILE: 56 PyErr_SetString(PyExc_IOError, 57 "got end of file during message"); 58 break; 59 case MP_BAD_MESSAGE_LENGTH: 60 PyErr_SetString(PyExc_IOError, "bad message length"); 61 break; 62 case MP_EXCEPTION_HAS_BEEN_SET: 63 break; 64 default: 65 PyErr_Format(PyExc_RuntimeError, 66 "unknown error number %d", num); 67 } 68 return NULL; 63 69 } 64 70 … … 77 83 ProcessingCtrlHandler(DWORD dwCtrlType) 78 84 { 79 80 85 SetEvent(sigint_event); 86 return FALSE; 81 87 } 82 88 … … 92 98 Reimplements some of the functionality of the fdcred 93 99 module at http://www.mca-ltd.com/resources/fdcred_1.tgz. */ 100 /* Based in http://resin.csoft.net/cgi-bin/man.cgi?section=3&topic=CMSG_DATA */ 94 101 95 102 static PyObject * 96 103 multiprocessing_sendfd(PyObject *self, PyObject *args) 97 104 { 98 int conn, fd, res; 99 char dummy_char; 100 char buf[CMSG_SPACE(sizeof(int))]; 101 struct msghdr msg = {0}; 102 struct iovec dummy_iov; 103 struct cmsghdr *cmsg; 104 105 if (!PyArg_ParseTuple(args, "ii", &conn, &fd)) 106 return NULL; 107 108 dummy_iov.iov_base = &dummy_char; 109 dummy_iov.iov_len = 1; 110 msg.msg_control = buf; 111 msg.msg_controllen = sizeof(buf); 112 msg.msg_iov = &dummy_iov; 113 msg.msg_iovlen = 1; 114 cmsg = CMSG_FIRSTHDR(&msg); 115 cmsg->cmsg_level = SOL_SOCKET; 116 cmsg->cmsg_type = SCM_RIGHTS; 117 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 118 msg.msg_controllen = cmsg->cmsg_len; 119 *(int*)CMSG_DATA(cmsg) = fd; 120 121 Py_BEGIN_ALLOW_THREADS 122 res = sendmsg(conn, &msg, 0); 123 Py_END_ALLOW_THREADS 124 125 if (res < 0) 126 return PyErr_SetFromErrno(PyExc_OSError); 127 Py_RETURN_NONE; 105 int conn, fd, res; 106 struct iovec dummy_iov; 107 char dummy_char; 108 struct msghdr msg; 109 struct cmsghdr *cmsg; 110 union { 111 struct cmsghdr hdr; 112 unsigned char buf[CMSG_SPACE(sizeof(int))]; 113 } cmsgbuf; 114 115 if (!PyArg_ParseTuple(args, "ii", &conn, &fd)) 116 return NULL; 117 118 dummy_iov.iov_base = &dummy_char; 119 dummy_iov.iov_len = 1; 120 121 memset(&msg, 0, sizeof(msg)); 122 msg.msg_control = &cmsgbuf.buf; 123 msg.msg_controllen = sizeof(cmsgbuf.buf); 124 msg.msg_iov = &dummy_iov; 125 msg.msg_iovlen = 1; 126 127 cmsg = CMSG_FIRSTHDR(&msg); 128 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 129 cmsg->cmsg_level = SOL_SOCKET; 130 cmsg->cmsg_type = SCM_RIGHTS; 131 * (int *) CMSG_DATA(cmsg) = fd; 132 133 Py_BEGIN_ALLOW_THREADS 134 res = sendmsg(conn, &msg, 0); 135 Py_END_ALLOW_THREADS 136 137 if (res < 0) 138 return PyErr_SetFromErrno(PyExc_OSError); 139 Py_RETURN_NONE; 128 140 } 129 141 … … 131 143 multiprocessing_recvfd(PyObject *self, PyObject *args) 132 144 { 133 int conn, fd, res; 134 char dummy_char; 135 char buf[CMSG_SPACE(sizeof(int))]; 136 struct msghdr msg = {0}; 137 struct iovec dummy_iov; 138 struct cmsghdr *cmsg; 139 140 if (!PyArg_ParseTuple(args, "i", &conn)) 141 return NULL; 142 143 dummy_iov.iov_base = &dummy_char; 144 dummy_iov.iov_len = 1; 145 msg.msg_control = buf; 146 msg.msg_controllen = sizeof(buf); 147 msg.msg_iov = &dummy_iov; 148 msg.msg_iovlen = 1; 149 cmsg = CMSG_FIRSTHDR(&msg); 150 cmsg->cmsg_level = SOL_SOCKET; 151 cmsg->cmsg_type = SCM_RIGHTS; 152 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 153 msg.msg_controllen = cmsg->cmsg_len; 154 155 Py_BEGIN_ALLOW_THREADS 156 res = recvmsg(conn, &msg, 0); 157 Py_END_ALLOW_THREADS 158 159 if (res < 0) 160 return PyErr_SetFromErrno(PyExc_OSError); 161 162 fd = *(int*)CMSG_DATA(cmsg); 163 return Py_BuildValue("i", fd); 145 int conn, fd, res; 146 char dummy_char; 147 struct iovec dummy_iov; 148 struct msghdr msg = {0}; 149 struct cmsghdr *cmsg; 150 union { 151 struct cmsghdr hdr; 152 unsigned char buf[CMSG_SPACE(sizeof(int))]; 153 } cmsgbuf; 154 155 if (!PyArg_ParseTuple(args, "i", &conn)) 156 return NULL; 157 158 dummy_iov.iov_base = &dummy_char; 159 dummy_iov.iov_len = 1; 160 161 memset(&msg, 0, sizeof(msg)); 162 msg.msg_control = &cmsgbuf.buf; 163 msg.msg_controllen = sizeof(cmsgbuf.buf); 164 msg.msg_iov = &dummy_iov; 165 msg.msg_iovlen = 1; 166 167 cmsg = CMSG_FIRSTHDR(&msg); 168 cmsg->cmsg_level = SOL_SOCKET; 169 cmsg->cmsg_type = SCM_RIGHTS; 170 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 171 msg.msg_controllen = cmsg->cmsg_len; 172 173 Py_BEGIN_ALLOW_THREADS 174 res = recvmsg(conn, &msg, 0); 175 Py_END_ALLOW_THREADS 176 177 if (res < 0) 178 return PyErr_SetFromErrno(PyExc_OSError); 179 180 if (msg.msg_controllen < CMSG_LEN(sizeof(int)) || 181 (cmsg = CMSG_FIRSTHDR(&msg)) == NULL || 182 cmsg->cmsg_level != SOL_SOCKET || 183 cmsg->cmsg_type != SCM_RIGHTS || 184 cmsg->cmsg_len < CMSG_LEN(sizeof(int))) { 185 /* If at least one control message is present, there should be 186 no room for any further data in the buffer. */ 187 PyErr_SetString(PyExc_RuntimeError, "No file descriptor received"); 188 return NULL; 189 } 190 191 fd = * (int *) CMSG_DATA(cmsg); 192 return Py_BuildValue("i", fd); 164 193 } 165 194 … … 176 205 multiprocessing_address_of_buffer(PyObject *self, PyObject *obj) 177 206 { 178 179 180 181 182 183 184 return Py_BuildValue("N" F_PY_SSIZE_T, 185 207 void *buffer; 208 Py_ssize_t buffer_len; 209 210 if (PyObject_AsWriteBuffer(obj, &buffer, &buffer_len) < 0) 211 return NULL; 212 213 return Py_BuildValue("N" F_PY_SSIZE_T, 214 PyLong_FromVoidPtr(buffer), buffer_len); 186 215 } 187 216 … … 192 221 193 222 static PyMethodDef module_methods[] = { 194 {"address_of_buffer", multiprocessing_address_of_buffer, METH_O, 195 "address_of_buffer(obj) -> int\n" 196 223 {"address_of_buffer", multiprocessing_address_of_buffer, METH_O, 224 "address_of_buffer(obj) -> int\n" 225 "Return address of obj assuming obj supports buffer inteface"}, 197 226 #if HAVE_FD_TRANSFER 198 {"sendfd", multiprocessing_sendfd, METH_VARARGS, 199 200 201 202 203 204 205 206 #endif 207 227 {"sendfd", multiprocessing_sendfd, METH_VARARGS, 228 "sendfd(sockfd, fd) -> None\n" 229 "Send file descriptor given by fd over the unix domain socket\n" 230 "whose file decriptor is sockfd"}, 231 {"recvfd", multiprocessing_recvfd, METH_VARARGS, 232 "recvfd(sockfd) -> fd\n" 233 "Receive a file descriptor over a unix domain socket\n" 234 "whose file decriptor is sockfd"}, 235 #endif 236 {NULL} 208 237 }; 209 238 … … 216 245 init_multiprocessing(void) 217 246 { 218 PyObject *module, *temp, *value; 219 220 /* Initialize module */ 221 module = Py_InitModule("_multiprocessing", module_methods); 222 if (!module) 223 return; 224 225 /* Get copy of objects from pickle */ 226 temp = PyImport_ImportModule(PICKLE_MODULE); 227 if (!temp) 228 return; 229 pickle_dumps = PyObject_GetAttrString(temp, "dumps"); 230 pickle_loads = PyObject_GetAttrString(temp, "loads"); 231 pickle_protocol = PyObject_GetAttrString(temp, "HIGHEST_PROTOCOL"); 232 Py_XDECREF(temp); 233 234 /* Get copy of BufferTooShort */ 235 temp = PyImport_ImportModule("multiprocessing"); 236 if (!temp) 237 return; 238 BufferTooShort = PyObject_GetAttrString(temp, "BufferTooShort"); 239 Py_XDECREF(temp); 240 241 /* Add connection type to module */ 242 if (PyType_Ready(&ConnectionType) < 0) 243 return; 244 Py_INCREF(&ConnectionType); 245 PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); 246 247 #if defined(MS_WINDOWS) || HAVE_SEM_OPEN 248 /* Add SemLock type to module */ 249 if (PyType_Ready(&SemLockType) < 0) 250 return; 251 Py_INCREF(&SemLockType); 252 PyDict_SetItemString(SemLockType.tp_dict, "SEM_VALUE_MAX", 253 Py_BuildValue("i", SEM_VALUE_MAX)); 254 PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); 247 PyObject *module, *temp, *value; 248 249 /* Initialize module */ 250 module = Py_InitModule("_multiprocessing", module_methods); 251 if (!module) 252 return; 253 254 /* Get copy of objects from pickle */ 255 temp = PyImport_ImportModule(PICKLE_MODULE); 256 if (!temp) 257 return; 258 pickle_dumps = PyObject_GetAttrString(temp, "dumps"); 259 pickle_loads = PyObject_GetAttrString(temp, "loads"); 260 pickle_protocol = PyObject_GetAttrString(temp, "HIGHEST_PROTOCOL"); 261 Py_XDECREF(temp); 262 263 /* Get copy of BufferTooShort */ 264 temp = PyImport_ImportModule("multiprocessing"); 265 if (!temp) 266 return; 267 BufferTooShort = PyObject_GetAttrString(temp, "BufferTooShort"); 268 Py_XDECREF(temp); 269 270 /* Add connection type to module */ 271 if (PyType_Ready(&ConnectionType) < 0) 272 return; 273 Py_INCREF(&ConnectionType); 274 PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); 275 276 #if defined(MS_WINDOWS) || \ 277 (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) 278 /* Add SemLock type to module */ 279 if (PyType_Ready(&SemLockType) < 0) 280 return; 281 Py_INCREF(&SemLockType); 282 { 283 PyObject *py_sem_value_max; 284 /* Some systems define SEM_VALUE_MAX as an unsigned value that 285 * causes it to be negative when used as an int (NetBSD). */ 286 if ((int)(SEM_VALUE_MAX) < 0) 287 py_sem_value_max = PyLong_FromLong(INT_MAX); 288 else 289 py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); 290 if (py_sem_value_max == NULL) 291 return; 292 PyDict_SetItemString(SemLockType.tp_dict, "SEM_VALUE_MAX", 293 py_sem_value_max); 294 } 295 PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); 255 296 #endif 256 297 257 298 #ifdef MS_WINDOWS 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 #endif 282 283 284 285 286 287 #define ADD_FLAG(name) 288 value = Py_BuildValue("i", name);\289 if (value == NULL) { Py_DECREF(temp); return; }\290 if (PyDict_SetItemString(temp, #name, value) < 0) {\291 Py_DECREF(temp); Py_DECREF(value); return; }\292 293 294 #if def HAVE_SEM_OPEN295 299 /* Add PipeConnection to module */ 300 if (PyType_Ready(&PipeConnectionType) < 0) 301 return; 302 Py_INCREF(&PipeConnectionType); 303 PyModule_AddObject(module, "PipeConnection", 304 (PyObject*)&PipeConnectionType); 305 306 /* Initialize win32 class and add to multiprocessing */ 307 temp = create_win32_namespace(); 308 if (!temp) 309 return; 310 PyModule_AddObject(module, "win32", temp); 311 312 /* Initialize the event handle used to signal Ctrl-C */ 313 sigint_event = CreateEvent(NULL, TRUE, FALSE, NULL); 314 if (!sigint_event) { 315 PyErr_SetFromWindowsErr(0); 316 return; 317 } 318 if (!SetConsoleCtrlHandler(ProcessingCtrlHandler, TRUE)) { 319 PyErr_SetFromWindowsErr(0); 320 return; 321 } 322 #endif 323 324 /* Add configuration macros */ 325 temp = PyDict_New(); 326 if (!temp) 327 return; 328 #define ADD_FLAG(name) \ 329 value = Py_BuildValue("i", name); \ 330 if (value == NULL) { Py_DECREF(temp); return; } \ 331 if (PyDict_SetItemString(temp, #name, value) < 0) { \ 332 Py_DECREF(temp); Py_DECREF(value); return; } \ 333 Py_DECREF(value) 334 335 #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) 336 ADD_FLAG(HAVE_SEM_OPEN); 296 337 #endif 297 338 #ifdef HAVE_SEM_TIMEDWAIT 298 339 ADD_FLAG(HAVE_SEM_TIMEDWAIT); 299 340 #endif 300 341 #ifdef HAVE_FD_TRANSFER 301 342 ADD_FLAG(HAVE_FD_TRANSFER); 302 343 #endif 303 344 #ifdef HAVE_BROKEN_SEM_GETVALUE 304 345 ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); 305 346 #endif 306 347 #ifdef HAVE_BROKEN_SEM_UNLINK 307 308 #endif 309 310 311 } 348 ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); 349 #endif 350 if (PyModule_AddObject(module, "flags", temp) < 0) 351 return; 352 }
Note:
See TracChangeset
for help on using the changeset viewer.