summaryrefslogtreecommitdiff
path: root/Modules/_multiprocessing
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_multiprocessing')
-rw-r--r--Modules/_multiprocessing/connection.h527
-rw-r--r--Modules/_multiprocessing/multiprocessing.c241
-rw-r--r--Modules/_multiprocessing/multiprocessing.h80
-rw-r--r--Modules/_multiprocessing/pipe_connection.c149
-rw-r--r--Modules/_multiprocessing/semaphore.c59
-rw-r--r--Modules/_multiprocessing/socket_connection.c202
-rw-r--r--Modules/_multiprocessing/win32_functions.c267
7 files changed, 72 insertions, 1453 deletions
diff --git a/Modules/_multiprocessing/connection.h b/Modules/_multiprocessing/connection.h
deleted file mode 100644
index 002d5aa9cc..0000000000
--- 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 ee250e0043..eb05c62b0d 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 14425de821..e3de9baf1b 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 05dde0cf39..0000000000
--- 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 1f37d6ac37..8ea92f2b58 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:
@@ -483,7 +472,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 *
@@ -507,7 +496,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 7ebf3389b3..0000000000
--- a/Modules/_multiprocessing/socket_connection.c
+++ /dev/null
@@ -1,202 +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)
-{
- int 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) {
- Py_BEGIN_ALLOW_THREADS
- res = _conn_recvall(conn->handle, buffer, (size_t)ulength);
- Py_END_ALLOW_THREADS
- return res < 0 ? res : ulength;
- } else {
- *newbuffer = PyMem_Malloc((size_t)ulength);
- if (*newbuffer == NULL)
- return MP_MEMORY_ERROR;
- Py_BEGIN_ALLOW_THREADS
- res = _conn_recvall(conn->handle, *newbuffer, (size_t)ulength);
- Py_END_ALLOW_THREADS
- return res < 0 ? (Py_ssize_t)res : (Py_ssize_t)ulength;
- }
-}
-
-/*
- * 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 0e348c4134..0000000000
--- 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;
-}