blob: 113b495a812f22eaa055ccd1f84e29e62c430983 [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.
33Under Unix, the file descriptors are small integers.
34Under Win32, select only exists for sockets, and sockets may
35have any value except INVALID_SOCKET.
36*/
Guido van Rossumed233a51992-06-23 09:07:03 +000037
38#include "allobjects.h"
39#include "modsupport.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000040#include "ceval.h"
41
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 Rossumb6775db1994-08-01 11:34:53 +000051#include <sys/types.h>
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000052
Guido van Rossum6f489d91996-06-28 20:15:15 +000053#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000054#include <winsock.h>
55#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000056#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000057#define SOCKET int
58#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000059
60static object *SelectError;
61
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000062typedef struct { /* list of Python objects and their file descriptor */
63 object *obj;
64 SOCKET fd;
65} pylist;
66
67static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000068list2set(list, set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +000069 object *list;
70 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000071 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000072{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000073 int i, len, index, max = -1;
Guido van Rossumed233a51992-06-23 09:07:03 +000074 object *o, *filenomethod, *fno;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000075 SOCKET v;
Guido van Rossum07432c01995-03-29 16:47:45 +000076
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000077 index = 0;
78 fd2obj[0].obj = (object*)0; /* set list to zero size */
Guido van Rossumed233a51992-06-23 09:07:03 +000079
80 FD_ZERO(set);
81 len = getlistsize(list);
82 for( i=0; i<len; i++ ) {
83 o = getlistitem(list, i);
84 if ( is_intobject(o) ) {
85 v = getintvalue(o);
86 } else if ( (filenomethod = getattr(o, "fileno")) != NULL ) {
87 fno = call_object(filenomethod, NULL);
Guido van Rossuma849b831993-05-12 11:35:44 +000088 DECREF(filenomethod);
Guido van Rossumed233a51992-06-23 09:07:03 +000089 if ( fno == NULL )
90 return -1;
91 if ( !is_intobject(fno) ) {
92 err_badarg();
Guido van Rossuma849b831993-05-12 11:35:44 +000093 DECREF(fno);
Guido van Rossumed233a51992-06-23 09:07:03 +000094 return -1;
95 }
96 v = getintvalue(fno);
97 DECREF(fno);
98 } else {
99 err_badarg();
100 return -1;
101 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000102#ifdef _MSC_VER
103 max = 0; /* not used for Win32 */
104#else
Guido van Rossumb6775db1994-08-01 11:34:53 +0000105 if ( v < 0 || v >= FD_SETSIZE ) {
106 err_setstr(ValueError, "filedescriptor out of range in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +0000107 return -1;
108 }
109 if ( v > max ) max = v;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000110#endif
Guido van Rossumed233a51992-06-23 09:07:03 +0000111 FD_SET(v, set);
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000112 /* add object and its file descriptor to the list */
113 if ( index >= FD_SETSIZE ) {
114 err_setstr(ValueError, "too many file descriptors in select()");
115 return -1;
116 }
117 fd2obj[index].obj = o;
118 fd2obj[index].fd = v;
119 fd2obj[++index].obj = (object *)0; /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000120 }
121 return max+1;
122}
123
124static object *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000125set2list(set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +0000126 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000127 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000128{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000129 int j, num=0;
Guido van Rossumed233a51992-06-23 09:07:03 +0000130 object *list, *o;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000131 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000132
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000133 for(j=0; fd2obj[j].obj; j++)
134 if ( FD_ISSET(fd2obj[j].fd, set) )
Guido van Rossumed233a51992-06-23 09:07:03 +0000135 num++;
136 list = newlistobject(num);
137 num = 0;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000138 for(j=0; fd2obj[j].obj; j++) {
139 fd = fd2obj[j].fd;
140 if ( FD_ISSET(fd, set) ) {
141#ifndef _MSC_VER
142 if ( fd > FD_SETSIZE ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000143 err_setstr(SystemError,
144 "filedescriptor out of range returned in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +0000145 return NULL;
146 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000147#endif
148 o = fd2obj[j].obj;
Guido van Rossumed233a51992-06-23 09:07:03 +0000149 INCREF(o);
150 setlistitem(list, num, o);
151 num++;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000152 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000153 }
154 return list;
155}
156
157static object *
158select_select(self, args)
159 object *self;
160 object *args;
161{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000162 pylist rfd2obj[FD_SETSIZE + 3], wfd2obj[FD_SETSIZE + 3], efd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000163 object *ifdlist, *ofdlist, *efdlist;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000164 object *ret, *tout;
Guido van Rossumed233a51992-06-23 09:07:03 +0000165 fd_set ifdset, ofdset, efdset;
166 double timeout;
167 struct timeval tv, *tvp;
168 int seconds;
169 int imax, omax, emax, max;
170 int n;
171
172
173 /* Get args. Looks funny because of optional timeout argument */
Guido van Rossumc7a22701993-11-01 16:27:16 +0000174 if ( getargs(args, "(OOOO)", &ifdlist, &ofdlist, &efdlist, &tout) ) {
Guido van Rossumc7a22701993-11-01 16:27:16 +0000175 if (tout == None)
176 tvp = (struct timeval *)0;
177 else {
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000178 if (!getargs(tout, "d;timeout must be float or None", &timeout))
Guido van Rossumc7a22701993-11-01 16:27:16 +0000179 return NULL;
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000180 seconds = (int)timeout;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000181 timeout = timeout - (double)seconds;
182 tv.tv_sec = seconds;
183 tv.tv_usec = (int)(timeout*1000000.0);
184 tvp = &tv;
185 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000186 } else {
187 /* Doesn't have 4 args, that means no timeout */
188 err_clear();
189 if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
190 return 0;
191 tvp = (struct timeval *)0;
192 }
193 if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
194 !is_listobject(efdlist) ) {
195 err_badarg();
196 return 0;
197 }
198
Guido van Rossumed233a51992-06-23 09:07:03 +0000199 /* Convert lists to fd_sets, and get maximum fd number */
Guido van Rossum07432c01995-03-29 16:47:45 +0000200 if( (imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000201 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000202 if( (omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000203 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000204 if( (emax=list2set(efdlist, &efdset, efd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000205 return 0;
206 max = imax;
207 if ( omax > max ) max = omax;
208 if ( emax > max ) max = emax;
209
Guido van Rossumff4949e1992-08-05 19:58:53 +0000210 BGN_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000211 n = select(max, &ifdset, &ofdset, &efdset, tvp);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000212 END_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000213
214 if ( n < 0 ) {
215 err_errno(SelectError);
216 return 0;
217 }
218
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000219 if ( n == 0 ) { /* Speedup hack */
220 ifdlist = newlistobject(0);
221 ret = mkvalue("OOO", ifdlist, ifdlist, ifdlist);
222 XDECREF(ifdlist);
223 return ret;
224 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000225
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000226 ifdlist = set2list(&ifdset, rfd2obj);
227 ofdlist = set2list(&ofdset, wfd2obj);
228 efdlist = set2list(&efdset, efd2obj);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000229 ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
230 XDECREF(ifdlist);
231 XDECREF(ofdlist);
232 XDECREF(efdlist);
233 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000234}
235
236
237static struct methodlist select_methods[] = {
238 { "select", select_select },
239 { 0, 0 },
240};
241
242
243void
244initselect()
245{
246 object *m, *d;
247 m = initmodule("select", select_methods);
248 d = getmoduledict(m);
249 SelectError = newstringobject("select.error");
250 if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
251 fatal("Cannot define select.error");
252}