blob: c18d979828ebb7e75314085eb0bc6e1e358ef1f3 [file] [log] [blame]
Guido van Rossumed233a51992-06-23 09:07:03 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumed233a51992-06-23 09:07:03 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumed233a51992-06-23 09:07:03 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumed233a51992-06-23 09:07:03 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumed233a51992-06-23 09:07:03 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumed233a51992-06-23 09:07:03 +000029
30******************************************************************/
31
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000032/* select - Module containing unix select(2) call.
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000033 Under Unix, the file descriptors are small integers.
34 Under Win32, select only exists for sockets, and sockets may
35 have any value except INVALID_SOCKET.
Guido van Rossumbcc20741998-08-04 22:53:56 +000036 Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything
37 >= 0.
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000038*/
Guido van Rossumed233a51992-06-23 09:07:03 +000039
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000040#include "Python.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000041
Guido van Rossuma376cc51996-12-05 23:43:35 +000042#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
Guido van Rossum37273171996-12-09 18:47:43 +000046#ifdef __sgi
47/* This is missing from unistd.h */
48extern void bzero();
49#endif
50
Guido van Rossumff7e83d1999-08-27 20:39:37 +000051#ifndef DONT_HAVE_SYS_TYPES_H
Guido van Rossumb6775db1994-08-01 11:34:53 +000052#include <sys/types.h>
Guido van Rossumff7e83d1999-08-27 20:39:37 +000053#endif
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000054
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000055#if defined(PYOS_OS2)
56#include <sys/time.h>
57#include <utils.h>
58#endif
59
Guido van Rossum6f489d91996-06-28 20:15:15 +000060#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000061#include <winsock.h>
62#else
Guido van Rossumbcc20741998-08-04 22:53:56 +000063#ifdef __BEOS__
64#include <net/socket.h>
65#define SOCKET int
66#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000067#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000068#define SOCKET int
69#endif
Guido van Rossumbcc20741998-08-04 22:53:56 +000070#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000071
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000072static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000073
Barry Warsawc1cb3601996-12-12 22:16:21 +000074/* list of Python objects and their file descriptor */
75typedef struct {
76 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000077 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000078 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000079} pylist;
80
Barry Warsawc1cb3601996-12-12 22:16:21 +000081static void
82reap_obj(fd2obj)
83 pylist fd2obj[FD_SETSIZE + 3];
84{
85 int i;
86 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
87 Py_XDECREF(fd2obj[i].obj);
88 fd2obj[i].obj = NULL;
89 }
90 fd2obj[0].sentinel = -1;
91}
92
93
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000094/* returns -1 and sets the Python exception if an error occurred, otherwise
95 returns a number >= 0
96*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000097static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000098list2set(list, set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000099 PyObject *list;
100 fd_set *set;
101 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000102{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000103 int i;
104 int max = -1;
105 int index = 0;
106 int len = PyList_Size(list);
107 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +0000108
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000109 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000110 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000111
112 for (i = 0; i < len; i++) {
113 PyObject *meth;
114 SOCKET v;
115
116 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000117 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +0000118 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000119
Barry Warsawc1cb3601996-12-12 22:16:21 +0000120 Py_INCREF(o);
121
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000122 if (PyInt_Check(o)) {
123 v = PyInt_AsLong(o);
124 }
125 else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
126 {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000127 PyObject *fno = PyEval_CallObject(meth, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000128 Py_DECREF(meth);
129 if (fno == NULL)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000130 goto finally;
131
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000132 if (!PyInt_Check(fno)) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000133 PyErr_SetString(PyExc_TypeError,
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000134 "fileno method returned a non-integer");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000135 Py_DECREF(fno);
136 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000137 }
138 v = PyInt_AsLong(fno);
139 Py_DECREF(fno);
140 }
141 else {
142 PyErr_SetString(PyExc_TypeError,
Barry Warsawc1cb3601996-12-12 22:16:21 +0000143 "argument must be an int, or have a fileno() method.");
144 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000145 }
Guido van Rossumbcc20741998-08-04 22:53:56 +0000146#if defined(_MSC_VER) || defined(__BEOS__)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000147 max = 0; /* not used for Win32 */
148#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000149 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000150 PyErr_SetString(PyExc_ValueError,
151 "filedescriptor out of range in select()");
152 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000153 }
154 if (v > max)
155 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000156#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000157 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000158
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000159 /* add object and its file descriptor to the list */
160 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000161 PyErr_SetString(PyExc_ValueError,
162 "too many file descriptors in select()");
163 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000164 }
165 fd2obj[index].obj = o;
166 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000167 fd2obj[index].sentinel = 0;
168 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000169 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000170 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000171
172 finally:
173 Py_XDECREF(o);
174 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000175}
176
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000177/* returns NULL and sets the Python exception if an error occurred */
178static PyObject *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000179set2list(set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000180 fd_set *set;
181 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000182{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000183 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000184 PyObject *list, *o;
185 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000186
Barry Warsawc1cb3601996-12-12 22:16:21 +0000187 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000188 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000189 count++;
190 }
191 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000192 if (!list)
193 return NULL;
194
Barry Warsawc1cb3601996-12-12 22:16:21 +0000195 i = 0;
196 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000197 fd = fd2obj[j].fd;
198 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000199#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000200 if (fd > FD_SETSIZE) {
201 PyErr_SetString(PyExc_SystemError,
202 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000203 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000204 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000205#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000206 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000207 fd2obj[j].obj = NULL;
208 /* transfer ownership */
209 if (PyList_SetItem(list, i, o) < 0)
210 goto finally;
211
212 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000213 }
214 }
215 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000216 finally:
217 Py_DECREF(list);
218 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000219}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000220
Guido van Rossumed233a51992-06-23 09:07:03 +0000221
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000222static PyObject *
Guido van Rossumed233a51992-06-23 09:07:03 +0000223select_select(self, args)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000224 PyObject *self;
225 PyObject *args;
Guido van Rossumed233a51992-06-23 09:07:03 +0000226{
Guido van Rossumd20781b1998-07-02 02:53:36 +0000227#ifdef MS_WINDOWS
228 /* This would be an awful lot of stack space on Windows! */
229 pylist *rfd2obj, *wfd2obj, *efd2obj;
230#else
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000231 pylist rfd2obj[FD_SETSIZE + 3];
232 pylist wfd2obj[FD_SETSIZE + 3];
233 pylist efd2obj[FD_SETSIZE + 3];
Guido van Rossumd20781b1998-07-02 02:53:36 +0000234#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000235 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000236 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000237 PyObject *tout = Py_None;
238 fd_set ifdset, ofdset, efdset;
239 double timeout;
240 struct timeval tv, *tvp;
241 int seconds;
242 int imax, omax, emax, max;
243 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000244
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000245 /* convert arguments */
246 if (!PyArg_ParseTuple(args, "OOO|O",
247 &ifdlist, &ofdlist, &efdlist, &tout))
248 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000249
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000250 if (tout == Py_None)
251 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000252 else if (!PyArg_Parse(tout, "d", &timeout)) {
253 PyErr_SetString(PyExc_TypeError,
254 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000255 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000256 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000257 else {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000258 seconds = (int)timeout;
259 timeout = timeout - (double)seconds;
260 tv.tv_sec = seconds;
261 tv.tv_usec = (int)(timeout*1000000.0);
262 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000263 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000264
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000265 /* sanity check first three arguments */
266 if (!PyList_Check(ifdlist) ||
267 !PyList_Check(ofdlist) ||
268 !PyList_Check(efdlist))
269 {
270 PyErr_SetString(PyExc_TypeError,
271 "arguments 1-3 must be lists");
272 return NULL;
273 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000274
Guido van Rossumd20781b1998-07-02 02:53:36 +0000275#ifdef MS_WINDOWS
276 /* Allocate memory for the lists */
277 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
278 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
279 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
280 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
281 PyMem_XDEL(rfd2obj);
282 PyMem_XDEL(wfd2obj);
283 PyMem_XDEL(efd2obj);
284 return NULL;
285 }
286#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000287 /* Convert lists to fd_sets, and get maximum fd number
288 * propagates the Python exception set in list2set()
289 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000290 rfd2obj[0].sentinel = -1;
291 wfd2obj[0].sentinel = -1;
292 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000293 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000294 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000295 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000296 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000297 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000298 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000299 max = imax;
300 if (omax > max) max = omax;
301 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000302
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000303 Py_BEGIN_ALLOW_THREADS
304 n = select(max, &ifdset, &ofdset, &efdset, tvp);
305 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000306
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000307 if (n < 0) {
308 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000309 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000310 else if (n == 0) {
311 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000312 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000313 if (ifdlist) {
314 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
315 Py_DECREF(ifdlist);
316 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000317 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000318 else {
319 /* any of these three calls can raise an exception. it's more
320 convenient to test for this after all three calls... but
321 is that acceptable?
322 */
323 ifdlist = set2list(&ifdset, rfd2obj);
324 ofdlist = set2list(&ofdset, wfd2obj);
325 efdlist = set2list(&efdset, efd2obj);
326 if (PyErr_Occurred())
327 ret = NULL;
328 else
329 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000330
Barry Warsawc1cb3601996-12-12 22:16:21 +0000331 Py_DECREF(ifdlist);
332 Py_DECREF(ofdlist);
333 Py_DECREF(efdlist);
334 }
335
336 finally:
337 reap_obj(rfd2obj);
338 reap_obj(wfd2obj);
339 reap_obj(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000340#ifdef MS_WINDOWS
341 PyMem_DEL(rfd2obj);
342 PyMem_DEL(wfd2obj);
343 PyMem_DEL(efd2obj);
344#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000345 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000346}
347
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000348static char select_doc[] =
349"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
350\n\
351Wait until one or more file descriptors are ready for some kind of I/O.\n\
352The first three arguments are lists of file descriptors to be waited for:\n\
353rlist -- wait until ready for reading\n\
354wlist -- wait until ready for writing\n\
355xlist -- wait for an ``exceptional condition''\n\
356If only one kind of condition is required, pass [] for the other lists.\n\
357A file descriptor is either a socket or file object, or a small integer\n\
358gotten from a fileno() method call on one of those.\n\
359\n\
360The optional 4th argument specifies a timeout in seconds; it may be\n\
361a floating point number to specify fractions of seconds. If it is absent\n\
362or None, the call will never time out.\n\
363\n\
364The return value is a tuple of three lists corresponding to the first three\n\
365arguments; each contains the subset of the corresponding file descriptors\n\
366that are ready.\n\
367\n\
368*** IMPORTANT NOTICE ***\n\
369On Windows, only sockets are supported; on Unix, all file descriptors.";
370
Guido van Rossumed233a51992-06-23 09:07:03 +0000371
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000372static PyMethodDef select_methods[] = {
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000373 {"select", select_select, 1, select_doc},
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000374 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000375};
376
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000377static char module_doc[] =
378"This module supports asynchronous I/O on multiple file descriptors.\n\
379\n\
380*** IMPORTANT NOTICE ***\n\
381On Windows, only sockets are supported; on Unix, all file descriptors.";
Guido van Rossumed233a51992-06-23 09:07:03 +0000382
Guido van Rossum3886bb61998-12-04 18:50:17 +0000383DL_EXPORT(void)
Guido van Rossumed233a51992-06-23 09:07:03 +0000384initselect()
385{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000386 PyObject *m, *d;
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000387 m = Py_InitModule3("select", select_methods, module_doc);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000388 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000389 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000390 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000391}