diff options
Diffstat (limited to 'Modules/_multiprocessing')
-rw-r--r-- | Modules/_multiprocessing/connection.h | 527 | ||||
-rw-r--r-- | Modules/_multiprocessing/multiprocessing.c | 241 | ||||
-rw-r--r-- | Modules/_multiprocessing/multiprocessing.h | 80 | ||||
-rw-r--r-- | Modules/_multiprocessing/pipe_connection.c | 149 | ||||
-rw-r--r-- | Modules/_multiprocessing/semaphore.c | 59 | ||||
-rw-r--r-- | Modules/_multiprocessing/socket_connection.c | 205 | ||||
-rw-r--r-- | Modules/_multiprocessing/win32_functions.c | 267 |
7 files changed, 72 insertions, 1456 deletions
diff --git a/Modules/_multiprocessing/connection.h b/Modules/_multiprocessing/connection.h deleted file mode 100644 index 002d5aa9cc5..00000000000 --- a/Modules/_multiprocessing/connection.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Definition of a `Connection` type. - * Used by `socket_connection.c` and `pipe_connection.c`. - * - * connection.h - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#ifndef CONNECTION_H -#define CONNECTION_H - -/* - * Read/write flags - */ - -#define READABLE 1 -#define WRITABLE 2 - -#define CHECK_READABLE(self) \ - if (!(self->flags & READABLE)) { \ - PyErr_SetString(PyExc_IOError, "connection is write-only"); \ - return NULL; \ - } - -#define CHECK_WRITABLE(self) \ - if (!(self->flags & WRITABLE)) { \ - PyErr_SetString(PyExc_IOError, "connection is read-only"); \ - return NULL; \ - } - -/* - * Allocation and deallocation - */ - -static PyObject * -connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - ConnectionObject *self; - HANDLE handle; - BOOL readable = TRUE, writable = TRUE; - - static char *kwlist[] = {"handle", "readable", "writable", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, F_HANDLE "|ii", kwlist, - &handle, &readable, &writable)) - return NULL; - - if (handle == INVALID_HANDLE_VALUE || (Py_ssize_t)handle < 0) { - PyErr_Format(PyExc_IOError, "invalid handle %zd", - (Py_ssize_t)handle); - return NULL; - } - - if (!readable && !writable) { - PyErr_SetString(PyExc_ValueError, - "either readable or writable must be true"); - return NULL; - } - - self = PyObject_New(ConnectionObject, type); - if (self == NULL) - return NULL; - - self->weakreflist = NULL; - self->handle = handle; - self->flags = 0; - - if (readable) - self->flags |= READABLE; - if (writable) - self->flags |= WRITABLE; - assert(self->flags >= 1 && self->flags <= 3); - - return (PyObject*)self; -} - -static void -connection_dealloc(ConnectionObject* self) -{ - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject*)self); - - if (self->handle != INVALID_HANDLE_VALUE) { - Py_BEGIN_ALLOW_THREADS - CLOSE(self->handle); - Py_END_ALLOW_THREADS - } - PyObject_Del(self); -} - -/* - * Functions for transferring buffers - */ - -static PyObject * -connection_sendbytes(ConnectionObject *self, PyObject *args) -{ - Py_buffer pbuffer; - char *buffer; - Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN; - int res; - - if (!PyArg_ParseTuple(args, F_RBUFFER "*|" F_PY_SSIZE_T F_PY_SSIZE_T, - &pbuffer, &offset, &size)) - return NULL; - buffer = pbuffer.buf; - length = pbuffer.len; - - CHECK_WRITABLE(self); /* XXX release buffer in case of failure */ - - if (offset < 0) { - PyBuffer_Release(&pbuffer); - PyErr_SetString(PyExc_ValueError, "offset is negative"); - return NULL; - } - if (length < offset) { - PyBuffer_Release(&pbuffer); - PyErr_SetString(PyExc_ValueError, "buffer length < offset"); - return NULL; - } - - if (size == PY_SSIZE_T_MIN) { - size = length - offset; - } else { - if (size < 0) { - PyBuffer_Release(&pbuffer); - PyErr_SetString(PyExc_ValueError, "size is negative"); - return NULL; - } - if (offset + size > length) { - PyBuffer_Release(&pbuffer); - PyErr_SetString(PyExc_ValueError, - "buffer length < offset + size"); - return NULL; - } - } - - res = conn_send_string(self, buffer + offset, size); - - PyBuffer_Release(&pbuffer); - if (res < 0) { - if (PyErr_Occurred()) - return NULL; - else - return mp_SetError(PyExc_IOError, res); - } - - Py_RETURN_NONE; -} - -static PyObject * -connection_recvbytes(ConnectionObject *self, PyObject *args) -{ - char *freeme = NULL; - Py_ssize_t res, maxlength = PY_SSIZE_T_MAX; - PyObject *result = NULL; - - if (!PyArg_ParseTuple(args, "|" F_PY_SSIZE_T, &maxlength)) - return NULL; - - CHECK_READABLE(self); - - if (maxlength < 0) { - PyErr_SetString(PyExc_ValueError, "maxlength < 0"); - return NULL; - } - - res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE, - &freeme, maxlength); - - if (res < 0) { - if (res == MP_BAD_MESSAGE_LENGTH) { - if ((self->flags & WRITABLE) == 0) { - Py_BEGIN_ALLOW_THREADS - CLOSE(self->handle); - Py_END_ALLOW_THREADS - self->handle = INVALID_HANDLE_VALUE; - } else { - self->flags = WRITABLE; - } - } - mp_SetError(PyExc_IOError, res); - } else { - if (freeme == NULL) { - result = PyBytes_FromStringAndSize(self->buffer, res); - } else { - result = PyBytes_FromStringAndSize(freeme, res); - PyMem_Free(freeme); - } - } - - return result; -} - -static PyObject * -connection_recvbytes_into(ConnectionObject *self, PyObject *args) -{ - char *freeme = NULL, *buffer = NULL; - Py_ssize_t res, length, offset = 0; - PyObject *result = NULL; - Py_buffer pbuf; - - CHECK_READABLE(self); - - if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T, - &pbuf, &offset)) - return NULL; - - buffer = pbuf.buf; - length = pbuf.len; - - if (offset < 0) { - PyErr_SetString(PyExc_ValueError, "negative offset"); - goto _error; - } - - if (offset > length) { - PyErr_SetString(PyExc_ValueError, "offset too large"); - goto _error; - } - - res = conn_recv_string(self, buffer+offset, length-offset, - &freeme, PY_SSIZE_T_MAX); - - if (res < 0) { - if (res == MP_BAD_MESSAGE_LENGTH) { - if ((self->flags & WRITABLE) == 0) { - Py_BEGIN_ALLOW_THREADS - CLOSE(self->handle); - Py_END_ALLOW_THREADS - self->handle = INVALID_HANDLE_VALUE; - } else { - self->flags = WRITABLE; - } - } - mp_SetError(PyExc_IOError, res); - } else { - if (freeme == NULL) { - result = PyInt_FromSsize_t(res); - } else { - result = PyObject_CallFunction(BufferTooShort, - F_RBUFFER "#", - freeme, res); - PyMem_Free(freeme); - if (result) { - PyErr_SetObject(BufferTooShort, result); - Py_DECREF(result); - } - goto _error; - } - } - -_cleanup: - PyBuffer_Release(&pbuf); - return result; - -_error: - result = NULL; - goto _cleanup; -} - -/* - * Functions for transferring objects - */ - -static PyObject * -connection_send_obj(ConnectionObject *self, PyObject *obj) -{ - char *buffer; - int res; - Py_ssize_t length; - PyObject *pickled_string = NULL; - - CHECK_WRITABLE(self); - - pickled_string = PyObject_CallFunctionObjArgs(pickle_dumps, obj, - pickle_protocol, NULL); - if (!pickled_string) - goto failure; - - if (PyBytes_AsStringAndSize(pickled_string, &buffer, &length) < 0) - goto failure; - - res = conn_send_string(self, buffer, (int)length); - - if (res < 0) { - mp_SetError(PyExc_IOError, res); - goto failure; - } - - Py_XDECREF(pickled_string); - Py_RETURN_NONE; - - failure: - Py_XDECREF(pickled_string); - return NULL; -} - -static PyObject * -connection_recv_obj(ConnectionObject *self) -{ - char *freeme = NULL; - Py_ssize_t res; - PyObject *temp = NULL, *result = NULL; - - CHECK_READABLE(self); - - res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE, - &freeme, PY_SSIZE_T_MAX); - - if (res < 0) { - if (res == MP_BAD_MESSAGE_LENGTH) { - if ((self->flags & WRITABLE) == 0) { - Py_BEGIN_ALLOW_THREADS - CLOSE(self->handle); - Py_END_ALLOW_THREADS - self->handle = INVALID_HANDLE_VALUE; - } else { - self->flags = WRITABLE; - } - } - mp_SetError(PyExc_IOError, res); - } else { - if (freeme == NULL) { - temp = PyBytes_FromStringAndSize(self->buffer, res); - } else { - temp = PyBytes_FromStringAndSize(freeme, res); - PyMem_Free(freeme); - } - } - - if (temp) - result = PyObject_CallFunctionObjArgs(pickle_loads, - temp, NULL); - Py_XDECREF(temp); - return result; -} - -/* - * Other functions - */ - -static PyObject * -connection_poll(ConnectionObject *self, PyObject *args) -{ - PyObject *timeout_obj = NULL; - double timeout = 0.0; - int res; - - CHECK_READABLE(self); - - if (!PyArg_ParseTuple(args, "|O", &timeout_obj)) - return NULL; - - if (timeout_obj == NULL) { - timeout = 0.0; - } else if (timeout_obj == Py_None) { - timeout = -1.0; /* block forever */ - } else { - timeout = PyFloat_AsDouble(timeout_obj); - if (PyErr_Occurred()) - return NULL; - if (timeout < 0.0) - timeout = 0.0; - } - - Py_BEGIN_ALLOW_THREADS - res = conn_poll(self, timeout, _save); - Py_END_ALLOW_THREADS - - switch (res) { - case TRUE: - Py_RETURN_TRUE; - case FALSE: - Py_RETURN_FALSE; - default: - return mp_SetError(PyExc_IOError, res); - } -} - -static PyObject * -connection_fileno(ConnectionObject* self) -{ - if (self->handle == INVALID_HANDLE_VALUE) { - PyErr_SetString(PyExc_IOError, "handle is invalid"); - return NULL; - } - return PyInt_FromLong((long)self->handle); -} - -static PyObject * -connection_close(ConnectionObject *self) -{ - if (self->handle != INVALID_HANDLE_VALUE) { - Py_BEGIN_ALLOW_THREADS - CLOSE(self->handle); - Py_END_ALLOW_THREADS - self->handle = INVALID_HANDLE_VALUE; - } - - Py_RETURN_NONE; -} - -static PyObject * -connection_repr(ConnectionObject *self) -{ - static char *conn_type[] = {"read-only", "write-only", "read-write"}; - - assert(self->flags >= 1 && self->flags <= 3); - return FROM_FORMAT("<%s %s, handle %zd>", - conn_type[self->flags - 1], - CONNECTION_NAME, (Py_ssize_t)self->handle); -} - -/* - * Getters and setters - */ - -static PyObject * -connection_closed(ConnectionObject *self, void *closure) -{ - return PyBool_FromLong((long)(self->handle == INVALID_HANDLE_VALUE)); -} - -static PyObject * -connection_readable(ConnectionObject *self, void *closure) -{ - return PyBool_FromLong((long)(self->flags & READABLE)); -} - -static PyObject * -connection_writable(ConnectionObject *self, void *closure) -{ - return PyBool_FromLong((long)(self->flags & WRITABLE)); -} - -/* - * Tables - */ - -static PyMethodDef connection_methods[] = { - {"send_bytes", (PyCFunction)connection_sendbytes, METH_VARARGS, - "send the byte data from a readable buffer-like object"}, - {"recv_bytes", (PyCFunction)connection_recvbytes, METH_VARARGS, - "receive byte data as a string"}, - {"recv_bytes_into",(PyCFunction)connection_recvbytes_into,METH_VARARGS, - "receive byte data into a writeable buffer-like object\n" - "returns the number of bytes read"}, - - {"send", (PyCFunction)connection_send_obj, METH_O, - "send a (picklable) object"}, - {"recv", (PyCFunction)connection_recv_obj, METH_NOARGS, - "receive a (picklable) object"}, - - {"poll", (PyCFunction)connection_poll, METH_VARARGS, - "whether there is any input available to be read"}, - {"fileno", (PyCFunction)connection_fileno, METH_NOARGS, - "file descriptor or handle of the connection"}, - {"close", (PyCFunction)connection_close, METH_NOARGS, - "close the connection"}, - - {NULL} /* Sentinel */ -}; - -static PyGetSetDef connection_getset[] = { - {"closed", (getter)connection_closed, NULL, - "True if the connection is closed", NULL}, - {"readable", (getter)connection_readable, NULL, - "True if the connection is readable", NULL}, - {"writable", (getter)connection_writable, NULL, - "True if the connection is writable", NULL}, - {NULL} -}; - -/* - * Connection type - */ - -PyDoc_STRVAR(connection_doc, - "Connection type whose constructor signature is\n\n" - " Connection(handle, readable=True, writable=True).\n\n" - "The constructor does *not* duplicate the handle."); - -PyTypeObject CONNECTION_TYPE = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_multiprocessing." CONNECTION_NAME, - /* tp_basicsize */ sizeof(ConnectionObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)connection_dealloc, - /* tp_print */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_reserved */ 0, - /* tp_repr */ (reprfunc)connection_repr, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_WEAKREFS, - /* tp_doc */ connection_doc, - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ offsetof(ConnectionObject, weakreflist), - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ connection_methods, - /* tp_members */ 0, - /* tp_getset */ connection_getset, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ connection_new, -}; - -#endif /* CONNECTION_H */ diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index ee250e00439..eb05c62b0d0 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -3,20 +3,13 @@ * * multiprocessing.c * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt + * Copyright (c) 2006-2008, R Oudkerk + * Licensed to PSF under a Contributor Agreement. */ #include "multiprocessing.h" -#if (defined(CMSG_LEN) && defined(SCM_RIGHTS)) - #define HAVE_FD_TRANSFER 1 -#else - #define HAVE_FD_TRANSFER 0 -#endif - -PyObject *create_win32_namespace(void); -PyObject *pickle_dumps, *pickle_loads, *pickle_protocol; PyObject *ProcessError, *BufferTooShort; /* @@ -49,16 +42,6 @@ mp_SetError(PyObject *Type, int num) case MP_MEMORY_ERROR: PyErr_NoMemory(); break; - case MP_END_OF_FILE: - PyErr_SetNone(PyExc_EOFError); - break; - case MP_EARLY_END_OF_FILE: - PyErr_SetString(PyExc_IOError, - "got end of file during message"); - break; - case MP_BAD_MESSAGE_LENGTH: - PyErr_SetString(PyExc_IOError, "bad message length"); - break; case MP_EXCEPTION_HAS_BEEN_SET: break; default: @@ -68,170 +51,82 @@ mp_SetError(PyObject *Type, int num) return NULL; } - -/* - * Windows only - */ - #ifdef MS_WINDOWS - -/* On Windows we set an event to signal Ctrl-C; compare with timemodule.c */ - -HANDLE sigint_event = NULL; - -static BOOL WINAPI -ProcessingCtrlHandler(DWORD dwCtrlType) -{ - SetEvent(sigint_event); - return FALSE; -} - -/* - * Unix only - */ - -#else /* !MS_WINDOWS */ - -#if HAVE_FD_TRANSFER - -/* Functions for transferring file descriptors between processes. - Reimplements some of the functionality of the fdcred - module at http://www.mca-ltd.com/resources/fdcred_1.tgz. */ -/* Based in http://resin.csoft.net/cgi-bin/man.cgi?section=3&topic=CMSG_DATA */ - static PyObject * -multiprocessing_sendfd(PyObject *self, PyObject *args) +multiprocessing_closesocket(PyObject *self, PyObject *args) { - int conn, fd, res; - struct iovec dummy_iov; - char dummy_char; - struct msghdr msg; - struct cmsghdr *cmsg; - union { - struct cmsghdr hdr; - unsigned char buf[CMSG_SPACE(sizeof(int))]; - } cmsgbuf; - - if (!PyArg_ParseTuple(args, "ii", &conn, &fd)) - return NULL; - - dummy_iov.iov_base = &dummy_char; - dummy_iov.iov_len = 1; + HANDLE handle; + int ret; - memset(&msg, 0, sizeof(msg)); - msg.msg_control = &cmsgbuf.buf; - msg.msg_controllen = sizeof(cmsgbuf.buf); - msg.msg_iov = &dummy_iov; - msg.msg_iovlen = 1; - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - * (int *) CMSG_DATA(cmsg) = fd; + if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle)) + return NULL; Py_BEGIN_ALLOW_THREADS - res = sendmsg(conn, &msg, 0); + ret = closesocket((SOCKET) handle); Py_END_ALLOW_THREADS - if (res < 0) - return PyErr_SetFromErrno(PyExc_OSError); + if (ret) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); Py_RETURN_NONE; } static PyObject * -multiprocessing_recvfd(PyObject *self, PyObject *args) +multiprocessing_recv(PyObject *self, PyObject *args) { - int conn, fd, res; - char dummy_char; - struct iovec dummy_iov; - struct msghdr msg = {0}; - struct cmsghdr *cmsg; - union { - struct cmsghdr hdr; - unsigned char buf[CMSG_SPACE(sizeof(int))]; - } cmsgbuf; - - if (!PyArg_ParseTuple(args, "i", &conn)) - return NULL; - - dummy_iov.iov_base = &dummy_char; - dummy_iov.iov_len = 1; + HANDLE handle; + int size, nread; + PyObject *buf; - memset(&msg, 0, sizeof(msg)); - msg.msg_control = &cmsgbuf.buf; - msg.msg_controllen = sizeof(cmsgbuf.buf); - msg.msg_iov = &dummy_iov; - msg.msg_iovlen = 1; + if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size)) + return NULL; - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - msg.msg_controllen = cmsg->cmsg_len; + buf = PyBytes_FromStringAndSize(NULL, size); + if (!buf) + return NULL; Py_BEGIN_ALLOW_THREADS - res = recvmsg(conn, &msg, 0); + nread = recv((SOCKET) handle, PyBytes_AS_STRING(buf), size, 0); Py_END_ALLOW_THREADS - if (res < 0) - return PyErr_SetFromErrno(PyExc_OSError); - - if (msg.msg_controllen < CMSG_LEN(sizeof(int)) || - (cmsg = CMSG_FIRSTHDR(&msg)) == NULL || - cmsg->cmsg_level != SOL_SOCKET || - cmsg->cmsg_type != SCM_RIGHTS || - cmsg->cmsg_len < CMSG_LEN(sizeof(int))) { - /* If at least one control message is present, there should be - no room for any further data in the buffer. */ - PyErr_SetString(PyExc_RuntimeError, "No file descriptor received"); - return NULL; + if (nread < 0) { + Py_DECREF(buf); + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); } - - fd = * (int *) CMSG_DATA(cmsg); - return Py_BuildValue("i", fd); + _PyBytes_Resize(&buf, nread); + return buf; } -#endif /* HAVE_FD_TRANSFER */ - -#endif /* !MS_WINDOWS */ - - -/* - * All platforms - */ - -static PyObject* -multiprocessing_address_of_buffer(PyObject *self, PyObject *obj) +static PyObject * +multiprocessing_send(PyObject *self, PyObject *args) { - void *buffer; - Py_ssize_t buffer_len; + HANDLE handle; + Py_buffer buf; + int ret; - if (PyObject_AsWriteBuffer(obj, &buffer, &buffer_len) < 0) + if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) return NULL; - return Py_BuildValue("N" F_PY_SSIZE_T, - PyLong_FromVoidPtr(buffer), buffer_len); + Py_BEGIN_ALLOW_THREADS + ret = send((SOCKET) handle, buf.buf, buf.len, 0); + Py_END_ALLOW_THREADS + + PyBuffer_Release(&buf); + if (ret < 0) + return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); + return PyLong_FromLong(ret); } +#endif /* * Function table */ static PyMethodDef module_methods[] = { - {"address_of_buffer", multiprocessing_address_of_buffer, METH_O, - "address_of_buffer(obj) -> int\n" - "Return address of obj assuming obj supports buffer inteface"}, -#if HAVE_FD_TRANSFER - {"sendfd", multiprocessing_sendfd, METH_VARARGS, - "sendfd(sockfd, fd) -> None\n" - "Send file descriptor given by fd over the unix domain socket\n" - "whose file decriptor is sockfd"}, - {"recvfd", multiprocessing_recvfd, METH_VARARGS, - "recvfd(sockfd) -> fd\n" - "Receive a file descriptor over a unix domain socket\n" - "whose file decriptor is sockfd"}, +#ifdef MS_WINDOWS + {"closesocket", multiprocessing_closesocket, METH_VARARGS, ""}, + {"recv", multiprocessing_recv, METH_VARARGS, ""}, + {"send", multiprocessing_send, METH_VARARGS, ""}, #endif {NULL} }; @@ -257,22 +152,13 @@ static struct PyModuleDef multiprocessing_module = { PyMODINIT_FUNC PyInit__multiprocessing(void) { - PyObject *module, *temp, *value; + PyObject *module, *temp, *value = NULL; /* Initialize module */ module = PyModule_Create(&multiprocessing_module); if (!module) return NULL; - /* Get copy of objects from pickle */ - temp = PyImport_ImportModule(PICKLE_MODULE); - if (!temp) - return NULL; - pickle_dumps = PyObject_GetAttrString(temp, "dumps"); - pickle_loads = PyObject_GetAttrString(temp, "loads"); - pickle_protocol = PyObject_GetAttrString(temp, "HIGHEST_PROTOCOL"); - Py_XDECREF(temp); - /* Get copy of BufferTooShort */ temp = PyImport_ImportModule("multiprocessing"); if (!temp) @@ -280,12 +166,6 @@ PyInit__multiprocessing(void) BufferTooShort = PyObject_GetAttrString(temp, "BufferTooShort"); Py_XDECREF(temp); - /* Add connection type to module */ - if (PyType_Ready(&ConnectionType) < 0) - return NULL; - Py_INCREF(&ConnectionType); - PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); - #if defined(MS_WINDOWS) || \ (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) /* Add SemLock type to module */ @@ -308,32 +188,6 @@ PyInit__multiprocessing(void) PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); #endif -#ifdef MS_WINDOWS - /* Add PipeConnection to module */ - if (PyType_Ready(&PipeConnectionType) < 0) - return NULL; - Py_INCREF(&PipeConnectionType); - PyModule_AddObject(module, "PipeConnection", - (PyObject*)&PipeConnectionType); - - /* Initialize win32 class and add to multiprocessing */ - temp = create_win32_namespace(); - if (!temp) - return NULL; - PyModule_AddObject(module, "win32", temp); - - /* Initialize the event handle used to signal Ctrl-C */ - sigint_event = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!sigint_event) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - if (!SetConsoleCtrlHandler(ProcessingCtrlHandler, TRUE)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } -#endif - /* Add configuration macros */ temp = PyDict_New(); if (!temp) @@ -343,7 +197,7 @@ PyInit__multiprocessing(void) value = Py_BuildValue("i", name); \ if (value == NULL) { Py_DECREF(temp); return NULL; } \ if (PyDict_SetItemString(temp, #name, value) < 0) { \ - Py_DECREF(temp); Py_DECREF(value); return NULL; } \ + Py_DECREF(temp); Py_DECREF(value); return NULL; } \ Py_DECREF(value) #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) @@ -352,9 +206,6 @@ PyInit__multiprocessing(void) #ifdef HAVE_SEM_TIMEDWAIT ADD_FLAG(HAVE_SEM_TIMEDWAIT); #endif -#ifdef HAVE_FD_TRANSFER - ADD_FLAG(HAVE_FD_TRANSFER); -#endif #ifdef HAVE_BROKEN_SEM_GETVALUE ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); #endif diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h index 14425de8218..e3de9baf1b3 100644 --- a/Modules/_multiprocessing/multiprocessing.h +++ b/Modules/_multiprocessing/multiprocessing.h @@ -3,12 +3,6 @@ #define PY_SSIZE_T_CLEAN -#ifdef __sun -/* The control message API is only available on Solaris - if XPG 4.2 or later is requested. */ -#define _XOPEN_SOURCE 500 -#endif - #include "Python.h" #include "structmember.h" #include "pythread.h" @@ -29,10 +23,6 @@ # define SEM_VALUE_MAX LONG_MAX #else # include <fcntl.h> /* O_CREAT and O_EXCL */ -# include <netinet/in.h> -# include <sys/socket.h> -# include <sys/uio.h> -# include <arpa/inet.h> /* htonl() and ntohl() */ # if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) # include <semaphore.h> typedef sem_t *SEM_HANDLE; @@ -64,20 +54,6 @@ /* - * Make sure Py_ssize_t available - */ - -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) - typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -# define F_PY_SSIZE_T "i" -# define PyInt_FromSsize_t(n) PyInt_FromLong((long)n) -#else -# define F_PY_SSIZE_T "n" -#endif - -/* * Format codes */ @@ -105,12 +81,6 @@ # define T_SEM_HANDLE T_POINTER #endif -#if PY_VERSION_HEX >= 0x03000000 -# define F_RBUFFER "y" -#else -# define F_RBUFFER "s" -#endif - /* * Error codes which can be returned by functions called without GIL */ @@ -118,11 +88,8 @@ #define MP_SUCCESS (0) #define MP_STANDARD_ERROR (-1) #define MP_MEMORY_ERROR (-1001) -#define MP_END_OF_FILE (-1002) -#define MP_EARLY_END_OF_FILE (-1003) -#define MP_BAD_MESSAGE_LENGTH (-1004) -#define MP_SOCKET_ERROR (-1005) -#define MP_EXCEPTION_HAS_BEEN_SET (-1006) +#define MP_SOCKET_ERROR (-1002) +#define MP_EXCEPTION_HAS_BEEN_SET (-1003) PyObject *mp_SetError(PyObject *Type, int num); @@ -130,57 +97,14 @@ PyObject *mp_SetError(PyObject *Type, int num); * Externs - not all will really exist on all platforms */ -extern PyObject *pickle_dumps; -extern PyObject *pickle_loads; -extern PyObject *pickle_protocol; extern PyObject *BufferTooShort; extern PyTypeObject SemLockType; -extern PyTypeObject ConnectionType; extern PyTypeObject PipeConnectionType; -extern HANDLE sigint_event; - -/* - * Py3k compatibility - */ - -#if PY_VERSION_HEX >= 0x03000000 -# define PICKLE_MODULE "pickle" -# define FROM_FORMAT PyUnicode_FromFormat -# define PyInt_FromLong PyLong_FromLong -# define PyInt_FromSsize_t PyLong_FromSsize_t -#else -# define PICKLE_MODULE "cPickle" -# define FROM_FORMAT PyString_FromFormat -#endif - -#ifndef PyVarObject_HEAD_INIT -# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif - -#ifndef Py_TPFLAGS_HAVE_WEAKREFS -# define Py_TPFLAGS_HAVE_WEAKREFS 0 -#endif - -/* - * Connection definition - */ - -#define CONNECTION_BUFFER_SIZE 1024 - -typedef struct { - PyObject_HEAD - HANDLE handle; - int flags; - PyObject *weakreflist; - char buffer[CONNECTION_BUFFER_SIZE]; -} ConnectionObject; /* * Miscellaneous */ -#define MAX_MESSAGE_LENGTH 0x7fffffff - #ifndef MIN # define MIN(x, y) ((x) < (y) ? x : y) # define MAX(x, y) ((x) > (y) ? x : y) diff --git a/Modules/_multiprocessing/pipe_connection.c b/Modules/_multiprocessing/pipe_connection.c deleted file mode 100644 index 05dde0cf39f..00000000000 --- a/Modules/_multiprocessing/pipe_connection.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * A type which wraps a pipe handle in message oriented mode - * - * pipe_connection.c - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#include "multiprocessing.h" - -#define CLOSE(h) CloseHandle(h) - -/* - * Send string to the pipe; assumes in message oriented mode - */ - -static Py_ssize_t -conn_send_string(ConnectionObject *conn, char *string, size_t length) -{ - DWORD amount_written; - BOOL ret; - - Py_BEGIN_ALLOW_THREADS - ret = WriteFile(conn->handle, string, length, &amount_written, NULL); - Py_END_ALLOW_THREADS - - if (ret == 0 && GetLastError() == ERROR_NO_SYSTEM_RESOURCES) { - PyErr_Format(PyExc_ValueError, "Cannnot send %" PY_FORMAT_SIZE_T "d bytes over connection", length); - return MP_STANDARD_ERROR; - } - - return ret ? MP_SUCCESS : MP_STANDARD_ERROR; -} - -/* - * Attempts to read into buffer, or if buffer too small into *newbuffer. - * - * Returns number of bytes read. Assumes in message oriented mode. - */ - -static Py_ssize_t -conn_recv_string(ConnectionObject *conn, char *buffer, - size_t buflength, char **newbuffer, size_t maxlength) -{ - DWORD left, length, full_length, err; - BOOL ret; - *newbuffer = NULL; - - Py_BEGIN_ALLOW_THREADS - ret = ReadFile(conn->handle, buffer, MIN(buflength, maxlength), - &length, NULL); - Py_END_ALLOW_THREADS - if (ret) - return length; - - err = GetLastError(); - if (err != ERROR_MORE_DATA) { - if (err == ERROR_BROKEN_PIPE) - return MP_END_OF_FILE; - return MP_STANDARD_ERROR; - } - - if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, NULL, &left)) - return MP_STANDARD_ERROR; - - full_length = length + left; - if (full_length > maxlength) - return MP_BAD_MESSAGE_LENGTH; - - *newbuffer = PyMem_Malloc(full_length); - if (*newbuffer == NULL) - return MP_MEMORY_ERROR; - - memcpy(*newbuffer, buffer, length); - - Py_BEGIN_ALLOW_THREADS - ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL); - Py_END_ALLOW_THREADS - if (ret) { - assert(length == left); - return full_length; - } else { - PyMem_Free(*newbuffer); - return MP_STANDARD_ERROR; - } -} - -/* - * Check whether any data is available for reading - */ - -static int -conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save) -{ - DWORD bytes, deadline, delay; - int difference, res; - BOOL block = FALSE; - - if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL)) - return MP_STANDARD_ERROR; - - if (timeout == 0.0) - return bytes > 0; - - if (timeout < 0.0) - block = TRUE; - else - /* XXX does not check for overflow */ - deadline = GetTickCount() + (DWORD)(1000 * timeout + 0.5); - - Sleep(0); - - for (delay = 1 ; ; delay += 1) { - if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL)) - return MP_STANDARD_ERROR; - else if (bytes > 0) - return TRUE; - - if (!block) { - difference = deadline - GetTickCount(); - if (difference < 0) - return FALSE; - if ((int)delay > difference) - delay = difference; - } - - if (delay > 20) - delay = 20; - - Sleep(delay); - - /* check for signals */ - Py_BLOCK_THREADS - res = PyErr_CheckSignals(); - Py_UNBLOCK_THREADS - - if (res) - return MP_EXCEPTION_HAS_BEEN_SET; - } -} - -/* - * "connection.h" defines the PipeConnection type using the definitions above - */ - -#define CONNECTION_NAME "PipeConnection" -#define CONNECTION_TYPE PipeConnectionType - -#include "connection.h" diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 1ee224d5506..2c2b020e3bd 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -3,7 +3,8 @@ * * semaphore.c * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt + * Copyright (c) 2006-2008, R Oudkerk + * Licensed to PSF under a Contributor Agreement. */ #include "multiprocessing.h" @@ -62,7 +63,8 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) int blocking = 1; double timeout; PyObject *timeout_obj = Py_None; - DWORD res, full_msecs, msecs, start, ticks; + DWORD res, full_msecs, nhandles; + HANDLE handles[2], sigint_event; static char *kwlist[] = {"block", "timeout", NULL}; @@ -96,53 +98,40 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) Py_RETURN_TRUE; } - /* check whether we can acquire without blocking */ + /* check whether we can acquire without releasing the GIL and blocking */ if (WaitForSingleObject(self->handle, 0) == WAIT_OBJECT_0) { self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; } - msecs = full_msecs; - start = GetTickCount(); - - for ( ; ; ) { - HANDLE handles[2] = {self->handle, sigint_event}; + /* prepare list of handles */ + nhandles = 0; + handles[nhandles++] = self->handle; + if (_PyOS_IsMainThread()) { + sigint_event = _PyOS_SigintEvent(); + assert(sigint_event != NULL); + handles[nhandles++] = sigint_event; + } - /* do the wait */ - Py_BEGIN_ALLOW_THREADS + /* do the wait */ + Py_BEGIN_ALLOW_THREADS + if (sigint_event != NULL) ResetEvent(sigint_event); - res = WaitForMultipleObjects(2, handles, FALSE, msecs); - Py_END_ALLOW_THREADS - - /* handle result */ - if (res != WAIT_OBJECT_0 + 1) - break; - - /* got SIGINT so give signal handler a chance to run */ - Sleep(1); - - /* if this is main thread let KeyboardInterrupt be raised */ - if (PyErr_CheckSignals()) - return NULL; - - /* recalculate timeout */ - if (msecs != INFINITE) { - ticks = GetTickCount(); - if ((DWORD)(ticks - start) >= full_msecs) - Py_RETURN_FALSE; - msecs = full_msecs - (ticks - start); - } - } + res = WaitForMultipleObjects(nhandles, handles, FALSE, full_msecs); + Py_END_ALLOW_THREADS /* handle result */ switch (res) { case WAIT_TIMEOUT: Py_RETURN_FALSE; - case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 0: self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; + case WAIT_OBJECT_0 + 1: + errno = EINTR; + return PyErr_SetFromErrno(PyExc_IOError); case WAIT_FAILED: return PyErr_SetFromWindowsErr(0); default: @@ -490,7 +479,7 @@ semlock_dealloc(SemLockObject* self) static PyObject * semlock_count(SemLockObject *self) { - return PyInt_FromLong((long)self->count); + return PyLong_FromLong((long)self->count); } static PyObject * @@ -514,7 +503,7 @@ semlock_getvalue(SemLockObject *self) the number of waiting threads */ if (sval < 0) sval = 0; - return PyInt_FromLong((long)sval); + return PyLong_FromLong((long)sval); #endif } diff --git a/Modules/_multiprocessing/socket_connection.c b/Modules/_multiprocessing/socket_connection.c deleted file mode 100644 index 1169c0a9237..00000000000 --- a/Modules/_multiprocessing/socket_connection.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * A type which wraps a socket - * - * socket_connection.c - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#include "multiprocessing.h" - -#ifdef MS_WINDOWS -# define WRITE(h, buffer, length) send((SOCKET)h, buffer, length, 0) -# define READ(h, buffer, length) recv((SOCKET)h, buffer, length, 0) -# define CLOSE(h) closesocket((SOCKET)h) -#else -# define WRITE(h, buffer, length) write(h, buffer, length) -# define READ(h, buffer, length) read(h, buffer, length) -# define CLOSE(h) close(h) -#endif - -/* - * Send string to file descriptor - */ - -static Py_ssize_t -_conn_sendall(HANDLE h, char *string, size_t length) -{ - char *p = string; - Py_ssize_t res; - - while (length > 0) { - res = WRITE(h, p, length); - if (res < 0) - return MP_SOCKET_ERROR; - length -= res; - p += res; - } - - return MP_SUCCESS; -} - -/* - * Receive string of exact length from file descriptor - */ - -static Py_ssize_t -_conn_recvall(HANDLE h, char *buffer, size_t length) -{ - size_t remaining = length; - Py_ssize_t temp; - char *p = buffer; - - while (remaining > 0) { - temp = READ(h, p, remaining); - if (temp <= 0) { - if (temp == 0) - return remaining == length ? - MP_END_OF_FILE : MP_EARLY_END_OF_FILE; - else - return temp; - } - remaining -= temp; - p += temp; - } - - return MP_SUCCESS; -} - -/* - * Send a string prepended by the string length in network byte order - */ - -static Py_ssize_t -conn_send_string(ConnectionObject *conn, char *string, size_t length) -{ - Py_ssize_t res; - /* The "header" of the message is a 32 bit unsigned number (in - network order) which specifies the length of the "body". If - the message is shorter than about 16kb then it is quicker to - combine the "header" and the "body" of the message and send - them at once. */ - if (length < (16*1024)) { - char *message; - - message = PyMem_Malloc(length+4); - if (message == NULL) - return MP_MEMORY_ERROR; - - *(UINT32*)message = htonl((UINT32)length); - memcpy(message+4, string, length); - Py_BEGIN_ALLOW_THREADS - res = _conn_sendall(conn->handle, message, length+4); - Py_END_ALLOW_THREADS - PyMem_Free(message); - } else { - UINT32 lenbuff; - - if (length > MAX_MESSAGE_LENGTH) - return MP_BAD_MESSAGE_LENGTH; - - lenbuff = htonl((UINT32)length); - Py_BEGIN_ALLOW_THREADS - res = _conn_sendall(conn->handle, (char*)&lenbuff, 4) || - _conn_sendall(conn->handle, string, length); - Py_END_ALLOW_THREADS - } - return res; -} - -/* - * Attempts to read into buffer, or failing that into *newbuffer - * - * Returns number of bytes read. - */ - -static Py_ssize_t -conn_recv_string(ConnectionObject *conn, char *buffer, - size_t buflength, char **newbuffer, size_t maxlength) -{ - Py_ssize_t res; - UINT32 ulength; - - *newbuffer = NULL; - - Py_BEGIN_ALLOW_THREADS - res = _conn_recvall(conn->handle, (char*)&ulength, 4); - Py_END_ALLOW_THREADS - if (res < 0) - return res; - - ulength = ntohl(ulength); - if (ulength > maxlength) - return MP_BAD_MESSAGE_LENGTH; - - if (ulength > buflength) { - *newbuffer = buffer = PyMem_Malloc((size_t)ulength); - if (buffer == NULL) - return MP_MEMORY_ERROR; - } - - Py_BEGIN_ALLOW_THREADS - res = _conn_recvall(conn->handle, buffer, (size_t)ulength); - Py_END_ALLOW_THREADS - - if (res >= 0) { - res = (Py_ssize_t)ulength; - } else if (*newbuffer != NULL) { - PyMem_Free(*newbuffer); - *newbuffer = NULL; - } - return res; -} - -/* - * Check whether any data is available for reading -- neg timeout blocks - */ - -static int -conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save) -{ - int res; - fd_set rfds; - - /* - * Verify the handle, issue 3321. Not required for windows. - */ - #ifndef MS_WINDOWS - if (((int)conn->handle) < 0 || ((int)conn->handle) >= FD_SETSIZE) { - Py_BLOCK_THREADS - PyErr_SetString(PyExc_IOError, "handle out of range in select()"); - Py_UNBLOCK_THREADS - return MP_EXCEPTION_HAS_BEEN_SET; - } - #endif - - FD_ZERO(&rfds); - FD_SET((SOCKET)conn->handle, &rfds); - - if (timeout < 0.0) { - res = select((int)conn->handle+1, &rfds, NULL, NULL, NULL); - } else { - struct timeval tv; - tv.tv_sec = (long)timeout; - tv.tv_usec = (long)((timeout - tv.tv_sec) * 1e6 + 0.5); - res = select((int)conn->handle+1, &rfds, NULL, NULL, &tv); - } - - if (res < 0) { - return MP_SOCKET_ERROR; - } else if (FD_ISSET(conn->handle, &rfds)) { - return TRUE; - } else { - assert(res == 0); - return FALSE; - } -} - -/* - * "connection.h" defines the Connection type using defs above - */ - -#define CONNECTION_NAME "Connection" -#define CONNECTION_TYPE ConnectionType - -#include "connection.h" diff --git a/Modules/_multiprocessing/win32_functions.c b/Modules/_multiprocessing/win32_functions.c deleted file mode 100644 index 0e348c4134f..00000000000 --- a/Modules/_multiprocessing/win32_functions.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Win32 functions used by multiprocessing package - * - * win32_functions.c - * - * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt - */ - -#include "multiprocessing.h" - - -#define WIN32_FUNCTION(func) \ - {#func, (PyCFunction)win32_ ## func, METH_VARARGS | METH_STATIC, ""} - -#define WIN32_CONSTANT(fmt, con) \ - PyDict_SetItemString(Win32Type.tp_dict, #con, Py_BuildValue(fmt, con)) - - -static PyObject * -win32_CloseHandle(PyObject *self, PyObject *args) -{ - HANDLE hObject; - BOOL success; - - if (!PyArg_ParseTuple(args, F_HANDLE, &hObject)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = CloseHandle(hObject); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_ConnectNamedPipe(PyObject *self, PyObject *args) -{ - HANDLE hNamedPipe; - LPOVERLAPPED lpOverlapped; - BOOL success; - - if (!PyArg_ParseTuple(args, F_HANDLE F_POINTER, - &hNamedPipe, &lpOverlapped)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = ConnectNamedPipe(hNamedPipe, lpOverlapped); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_CreateFile(PyObject *self, PyObject *args) -{ - LPCTSTR lpFileName; - DWORD dwDesiredAccess; - DWORD dwShareMode; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes; - HANDLE hTemplateFile; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_POINTER - F_DWORD F_DWORD F_HANDLE, - &lpFileName, &dwDesiredAccess, &dwShareMode, - &lpSecurityAttributes, &dwCreationDisposition, - &dwFlagsAndAttributes, &hTemplateFile)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateFile(lpFileName, dwDesiredAccess, - dwShareMode, lpSecurityAttributes, - dwCreationDisposition, - dwFlagsAndAttributes, hTemplateFile); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_CreateNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpName; - DWORD dwOpenMode; - DWORD dwPipeMode; - DWORD nMaxInstances; - DWORD nOutBufferSize; - DWORD nInBufferSize; - DWORD nDefaultTimeOut; - LPSECURITY_ATTRIBUTES lpSecurityAttributes; - HANDLE handle; - - if (!PyArg_ParseTuple(args, "s" F_DWORD F_DWORD F_DWORD - F_DWORD F_DWORD F_DWORD F_POINTER, - &lpName, &dwOpenMode, &dwPipeMode, - &nMaxInstances, &nOutBufferSize, - &nInBufferSize, &nDefaultTimeOut, - &lpSecurityAttributes)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - handle = CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, - nMaxInstances, nOutBufferSize, - nInBufferSize, nDefaultTimeOut, - lpSecurityAttributes); - Py_END_ALLOW_THREADS - - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_ExitProcess(PyObject *self, PyObject *args) -{ - UINT uExitCode; - - if (!PyArg_ParseTuple(args, "I", &uExitCode)) - return NULL; - - #if defined(Py_DEBUG) - SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOALIGNMENTFAULTEXCEPT|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); - #endif - - - ExitProcess(uExitCode); - - return NULL; -} - -static PyObject * -win32_GetLastError(PyObject *self, PyObject *args) -{ - return Py_BuildValue(F_DWORD, GetLastError()); -} - -static PyObject * -win32_OpenProcess(PyObject *self, PyObject *args) -{ - DWORD dwDesiredAccess; - BOOL bInheritHandle; - DWORD dwProcessId; - HANDLE handle; - - if (!PyArg_ParseTuple(args, F_DWORD "i" F_DWORD, - &dwDesiredAccess, &bInheritHandle, &dwProcessId)) - return NULL; - - handle = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); - if (handle == NULL) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue(F_HANDLE, handle); -} - -static PyObject * -win32_SetNamedPipeHandleState(PyObject *self, PyObject *args) -{ - HANDLE hNamedPipe; - PyObject *oArgs[3]; - DWORD dwArgs[3], *pArgs[3] = {NULL, NULL, NULL}; - int i; - - if (!PyArg_ParseTuple(args, F_HANDLE "OOO", - &hNamedPipe, &oArgs[0], &oArgs[1], &oArgs[2])) - return NULL; - - PyErr_Clear(); - - for (i = 0 ; i < 3 ; i++) { - if (oArgs[i] != Py_None) { - dwArgs[i] = PyLong_AsUnsignedLongMask(oArgs[i]); - if (PyErr_Occurred()) - return NULL; - pArgs[i] = &dwArgs[i]; - } - } - - if (!SetNamedPipeHandleState(hNamedPipe, pArgs[0], pArgs[1], pArgs[2])) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyObject * -win32_WaitNamedPipe(PyObject *self, PyObject *args) -{ - LPCTSTR lpNamedPipeName; - DWORD nTimeOut; - BOOL success; - - if (!PyArg_ParseTuple(args, "s" F_DWORD, &lpNamedPipeName, &nTimeOut)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - success = WaitNamedPipe(lpNamedPipeName, nTimeOut); - Py_END_ALLOW_THREADS - - if (!success) - return PyErr_SetFromWindowsErr(0); - - Py_RETURN_NONE; -} - -static PyMethodDef win32_methods[] = { - WIN32_FUNCTION(CloseHandle), - WIN32_FUNCTION(GetLastError), - WIN32_FUNCTION(OpenProcess), - WIN32_FUNCTION(ExitProcess), - WIN32_FUNCTION(ConnectNamedPipe), - WIN32_FUNCTION(CreateFile), - WIN32_FUNCTION(CreateNamedPipe), - WIN32_FUNCTION(SetNamedPipeHandleState), - WIN32_FUNCTION(WaitNamedPipe), - {NULL} -}; - - -PyTypeObject Win32Type = { - PyVarObject_HEAD_INIT(NULL, 0) -}; - - -PyObject * -create_win32_namespace(void) -{ - Win32Type.tp_name = "_multiprocessing.win32"; - Win32Type.tp_methods = win32_methods; - if (PyType_Ready(&Win32Type) < 0) - return NULL; - Py_INCREF(&Win32Type); - - WIN32_CONSTANT(F_DWORD, ERROR_ALREADY_EXISTS); - WIN32_CONSTANT(F_DWORD, ERROR_NO_DATA); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_BUSY); - WIN32_CONSTANT(F_DWORD, ERROR_PIPE_CONNECTED); - WIN32_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT); - WIN32_CONSTANT(F_DWORD, GENERIC_READ); - WIN32_CONSTANT(F_DWORD, GENERIC_WRITE); - WIN32_CONSTANT(F_DWORD, INFINITE); - WIN32_CONSTANT(F_DWORD, NMPWAIT_WAIT_FOREVER); - WIN32_CONSTANT(F_DWORD, OPEN_EXISTING); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_DUPLEX); - WIN32_CONSTANT(F_DWORD, PIPE_ACCESS_INBOUND); - WIN32_CONSTANT(F_DWORD, PIPE_READMODE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_TYPE_MESSAGE); - WIN32_CONSTANT(F_DWORD, PIPE_UNLIMITED_INSTANCES); - WIN32_CONSTANT(F_DWORD, PIPE_WAIT); - WIN32_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); - - WIN32_CONSTANT("i", NULL); - - return (PyObject*)&Win32Type; -} |