blob: 25665c6c9e3e18c5c30cafb3b715fbc4486d1946 [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
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000025/* select - Module containing unix select(2) call.
26Under Unix, the file descriptors are small integers.
27Under Win32, select only exists for sockets, and sockets may
28have any value except INVALID_SOCKET.
29*/
Guido van Rossumed233a51992-06-23 09:07:03 +000030
31#include "allobjects.h"
32#include "modsupport.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000033#include "ceval.h"
34
Guido van Rossumb6775db1994-08-01 11:34:53 +000035#include <sys/types.h>
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000036
Guido van Rossum6f489d91996-06-28 20:15:15 +000037#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000038#include <winsock.h>
39#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000040#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000041#define SOCKET int
42#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000043
44static object *SelectError;
45
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000046typedef struct { /* list of Python objects and their file descriptor */
47 object *obj;
48 SOCKET fd;
49} pylist;
50
51static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000052list2set(list, set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +000053 object *list;
54 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000055 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000056{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000057 int i, len, index, max = -1;
Guido van Rossumed233a51992-06-23 09:07:03 +000058 object *o, *filenomethod, *fno;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000059 SOCKET v;
Guido van Rossum07432c01995-03-29 16:47:45 +000060
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000061 index = 0;
62 fd2obj[0].obj = (object*)0; /* set list to zero size */
Guido van Rossumed233a51992-06-23 09:07:03 +000063
64 FD_ZERO(set);
65 len = getlistsize(list);
66 for( i=0; i<len; i++ ) {
67 o = getlistitem(list, i);
68 if ( is_intobject(o) ) {
69 v = getintvalue(o);
70 } else if ( (filenomethod = getattr(o, "fileno")) != NULL ) {
71 fno = call_object(filenomethod, NULL);
Guido van Rossuma849b831993-05-12 11:35:44 +000072 DECREF(filenomethod);
Guido van Rossumed233a51992-06-23 09:07:03 +000073 if ( fno == NULL )
74 return -1;
75 if ( !is_intobject(fno) ) {
76 err_badarg();
Guido van Rossuma849b831993-05-12 11:35:44 +000077 DECREF(fno);
Guido van Rossumed233a51992-06-23 09:07:03 +000078 return -1;
79 }
80 v = getintvalue(fno);
81 DECREF(fno);
82 } else {
83 err_badarg();
84 return -1;
85 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000086#ifdef _MSC_VER
87 max = 0; /* not used for Win32 */
88#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000089 if ( v < 0 || v >= FD_SETSIZE ) {
90 err_setstr(ValueError, "filedescriptor out of range in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +000091 return -1;
92 }
93 if ( v > max ) max = v;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000094#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000095 FD_SET(v, set);
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000096 /* add object and its file descriptor to the list */
97 if ( index >= FD_SETSIZE ) {
98 err_setstr(ValueError, "too many file descriptors in select()");
99 return -1;
100 }
101 fd2obj[index].obj = o;
102 fd2obj[index].fd = v;
103 fd2obj[++index].obj = (object *)0; /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000104 }
105 return max+1;
106}
107
108static object *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000109set2list(set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +0000110 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000111 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000112{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000113 int j, num=0;
Guido van Rossumed233a51992-06-23 09:07:03 +0000114 object *list, *o;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000115 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000116
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000117 for(j=0; fd2obj[j].obj; j++)
118 if ( FD_ISSET(fd2obj[j].fd, set) )
Guido van Rossumed233a51992-06-23 09:07:03 +0000119 num++;
120 list = newlistobject(num);
121 num = 0;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000122 for(j=0; fd2obj[j].obj; j++) {
123 fd = fd2obj[j].fd;
124 if ( FD_ISSET(fd, set) ) {
125#ifndef _MSC_VER
126 if ( fd > FD_SETSIZE ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000127 err_setstr(SystemError,
128 "filedescriptor out of range returned in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +0000129 return NULL;
130 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000131#endif
132 o = fd2obj[j].obj;
Guido van Rossumed233a51992-06-23 09:07:03 +0000133 INCREF(o);
134 setlistitem(list, num, o);
135 num++;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000136 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000137 }
138 return list;
139}
140
141static object *
142select_select(self, args)
143 object *self;
144 object *args;
145{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000146 pylist rfd2obj[FD_SETSIZE + 3], wfd2obj[FD_SETSIZE + 3], efd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000147 object *ifdlist, *ofdlist, *efdlist;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000148 object *ret, *tout;
Guido van Rossumed233a51992-06-23 09:07:03 +0000149 fd_set ifdset, ofdset, efdset;
150 double timeout;
151 struct timeval tv, *tvp;
152 int seconds;
153 int imax, omax, emax, max;
154 int n;
155
156
157 /* Get args. Looks funny because of optional timeout argument */
Guido van Rossumc7a22701993-11-01 16:27:16 +0000158 if ( getargs(args, "(OOOO)", &ifdlist, &ofdlist, &efdlist, &tout) ) {
Guido van Rossumc7a22701993-11-01 16:27:16 +0000159 if (tout == None)
160 tvp = (struct timeval *)0;
161 else {
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000162 if (!getargs(tout, "d;timeout must be float or None", &timeout))
Guido van Rossumc7a22701993-11-01 16:27:16 +0000163 return NULL;
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000164 seconds = (int)timeout;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000165 timeout = timeout - (double)seconds;
166 tv.tv_sec = seconds;
167 tv.tv_usec = (int)(timeout*1000000.0);
168 tvp = &tv;
169 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000170 } else {
171 /* Doesn't have 4 args, that means no timeout */
172 err_clear();
173 if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
174 return 0;
175 tvp = (struct timeval *)0;
176 }
177 if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
178 !is_listobject(efdlist) ) {
179 err_badarg();
180 return 0;
181 }
182
Guido van Rossumed233a51992-06-23 09:07:03 +0000183 /* Convert lists to fd_sets, and get maximum fd number */
Guido van Rossum07432c01995-03-29 16:47:45 +0000184 if( (imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000185 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000186 if( (omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000187 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000188 if( (emax=list2set(efdlist, &efdset, efd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000189 return 0;
190 max = imax;
191 if ( omax > max ) max = omax;
192 if ( emax > max ) max = emax;
193
Guido van Rossumff4949e1992-08-05 19:58:53 +0000194 BGN_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000195 n = select(max, &ifdset, &ofdset, &efdset, tvp);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000196 END_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000197
198 if ( n < 0 ) {
199 err_errno(SelectError);
200 return 0;
201 }
202
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000203 if ( n == 0 ) { /* Speedup hack */
204 ifdlist = newlistobject(0);
205 ret = mkvalue("OOO", ifdlist, ifdlist, ifdlist);
206 XDECREF(ifdlist);
207 return ret;
208 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000209
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000210 ifdlist = set2list(&ifdset, rfd2obj);
211 ofdlist = set2list(&ofdset, wfd2obj);
212 efdlist = set2list(&efdset, efd2obj);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000213 ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
214 XDECREF(ifdlist);
215 XDECREF(ofdlist);
216 XDECREF(efdlist);
217 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000218}
219
220
221static struct methodlist select_methods[] = {
222 { "select", select_select },
223 { 0, 0 },
224};
225
226
227void
228initselect()
229{
230 object *m, *d;
231 m = initmodule("select", select_methods);
232 d = getmoduledict(m);
233 SelectError = newstringobject("select.error");
234 if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
235 fatal("Cannot define select.error");
236}