~pythonregexp2.7/python/issue2636-11

« back to all changes in this revision

Viewing changes to Modules/_multiprocessing/pipe_connection.c

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-09-21 17:53:26 UTC
  • mfrom: (39025.1.14 Regexp-2.7)
  • Revision ID: darklord@timehorse.com-20080921175326-92vaej2hc3yuecxb
Merged in changes from the core Regexp branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * A type which wraps a pipe handle in message oriented mode
 
3
 *
 
4
 * pipe_connection.c
 
5
 *
 
6
 * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
 
7
 */
 
8
 
 
9
#include "multiprocessing.h"
 
10
 
 
11
#define CLOSE(h) CloseHandle(h)
 
12
 
 
13
/*
 
14
 * Send string to the pipe; assumes in message oriented mode
 
15
 */
 
16
 
 
17
static Py_ssize_t
 
18
conn_send_string(ConnectionObject *conn, char *string, size_t length)
 
19
{
 
20
        DWORD amount_written;
 
21
        BOOL ret;
 
22
 
 
23
        Py_BEGIN_ALLOW_THREADS
 
24
        ret = WriteFile(conn->handle, string, length, &amount_written, NULL);
 
25
        Py_END_ALLOW_THREADS
 
26
        return ret ? MP_SUCCESS : MP_STANDARD_ERROR;
 
27
}
 
28
 
 
29
/*
 
30
 * Attempts to read into buffer, or if buffer too small into *newbuffer.
 
31
 *
 
32
 * Returns number of bytes read.  Assumes in message oriented mode.
 
33
 */
 
34
 
 
35
static Py_ssize_t
 
36
conn_recv_string(ConnectionObject *conn, char *buffer, 
 
37
                 size_t buflength, char **newbuffer, size_t maxlength)
 
38
{
 
39
        DWORD left, length, full_length, err;
 
40
        BOOL ret;
 
41
        *newbuffer = NULL;
 
42
 
 
43
        Py_BEGIN_ALLOW_THREADS
 
44
        ret = ReadFile(conn->handle, buffer, MIN(buflength, maxlength), 
 
45
                      &length, NULL);
 
46
        Py_END_ALLOW_THREADS
 
47
        if (ret)
 
48
                return length;
 
49
 
 
50
        err = GetLastError();
 
51
        if (err != ERROR_MORE_DATA) {
 
52
                if (err == ERROR_BROKEN_PIPE)
 
53
                        return MP_END_OF_FILE;
 
54
                return MP_STANDARD_ERROR;
 
55
        }
 
56
 
 
57
        if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, NULL, &left))
 
58
                return MP_STANDARD_ERROR;
 
59
 
 
60
        full_length = length + left;
 
61
        if (full_length > maxlength)
 
62
                return MP_BAD_MESSAGE_LENGTH;
 
63
 
 
64
        *newbuffer = PyMem_Malloc(full_length);
 
65
        if (*newbuffer == NULL)
 
66
                return MP_MEMORY_ERROR;
 
67
 
 
68
        memcpy(*newbuffer, buffer, length);
 
69
 
 
70
        Py_BEGIN_ALLOW_THREADS
 
71
        ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL);
 
72
        Py_END_ALLOW_THREADS
 
73
        if (ret) {
 
74
                assert(length == left);
 
75
                return full_length;
 
76
        } else {
 
77
                PyMem_Free(*newbuffer);
 
78
                return MP_STANDARD_ERROR;
 
79
        }
 
80
}
 
81
 
 
82
/*
 
83
 * Check whether any data is available for reading
 
84
 */
 
85
 
 
86
#define conn_poll(conn, timeout) conn_poll_save(conn, timeout, _save)
 
87
 
 
88
static int
 
89
conn_poll_save(ConnectionObject *conn, double timeout, PyThreadState *_save)
 
90
{
 
91
        DWORD bytes, deadline, delay;
 
92
        int difference, res;
 
93
        BOOL block = FALSE;
 
94
 
 
95
        if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
 
96
                return MP_STANDARD_ERROR;
 
97
 
 
98
        if (timeout == 0.0)
 
99
                return bytes > 0;
 
100
 
 
101
        if (timeout < 0.0)
 
102
                block = TRUE;
 
103
        else
 
104
                /* XXX does not check for overflow */
 
105
                deadline = GetTickCount() + (DWORD)(1000 * timeout + 0.5);
 
106
 
 
107
        Sleep(0);
 
108
 
 
109
        for (delay = 1 ; ; delay += 1) {
 
110
                if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
 
111
                        return MP_STANDARD_ERROR;
 
112
                else if (bytes > 0)
 
113
                        return TRUE;
 
114
 
 
115
                if (!block) {
 
116
                        difference = deadline - GetTickCount();
 
117
                        if (difference < 0)
 
118
                                return FALSE;
 
119
                        if ((int)delay > difference)
 
120
                                delay = difference;
 
121
                }
 
122
 
 
123
                if (delay > 20)
 
124
                        delay = 20;
 
125
 
 
126
                Sleep(delay);
 
127
 
 
128
                /* check for signals */
 
129
                Py_BLOCK_THREADS 
 
130
                res = PyErr_CheckSignals();
 
131
                Py_UNBLOCK_THREADS
 
132
 
 
133
                if (res)
 
134
                        return MP_EXCEPTION_HAS_BEEN_SET;
 
135
        }
 
136
}
 
137
 
 
138
/*
 
139
 * "connection.h" defines the PipeConnection type using the definitions above
 
140
 */
 
141
 
 
142
#define CONNECTION_NAME "PipeConnection"
 
143
#define CONNECTION_TYPE PipeConnectionType
 
144
 
 
145
#include "connection.h"