blob: 3cbd4e8572c07681229cf92920f70d7807ab0874 [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 Rossumb6775db1994-08-01 11:34:53 +000046#include <sys/types.h>
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000047
Guido van Rossum6f489d91996-06-28 20:15:15 +000048#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000049#include <winsock.h>
50#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000051#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000052#define SOCKET int
53#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000054
55static object *SelectError;
56
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000057typedef struct { /* list of Python objects and their file descriptor */
58 object *obj;
59 SOCKET fd;
60} pylist;
61
62static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000063list2set(list, set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +000064 object *list;
65 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000066 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000067{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000068 int i, len, index, max = -1;
Guido van Rossumed233a51992-06-23 09:07:03 +000069 object *o, *filenomethod, *fno;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000070 SOCKET v;
Guido van Rossum07432c01995-03-29 16:47:45 +000071
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000072 index = 0;
73 fd2obj[0].obj = (object*)0; /* set list to zero size */
Guido van Rossumed233a51992-06-23 09:07:03 +000074
75 FD_ZERO(set);
76 len = getlistsize(list);
77 for( i=0; i<len; i++ ) {
78 o = getlistitem(list, i);
79 if ( is_intobject(o) ) {
80 v = getintvalue(o);
81 } else if ( (filenomethod = getattr(o, "fileno")) != NULL ) {
82 fno = call_object(filenomethod, NULL);
Guido van Rossuma849b831993-05-12 11:35:44 +000083 DECREF(filenomethod);
Guido van Rossumed233a51992-06-23 09:07:03 +000084 if ( fno == NULL )
85 return -1;
86 if ( !is_intobject(fno) ) {
87 err_badarg();
Guido van Rossuma849b831993-05-12 11:35:44 +000088 DECREF(fno);
Guido van Rossumed233a51992-06-23 09:07:03 +000089 return -1;
90 }
91 v = getintvalue(fno);
92 DECREF(fno);
93 } else {
94 err_badarg();
95 return -1;
96 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000097#ifdef _MSC_VER
98 max = 0; /* not used for Win32 */
99#else
Guido van Rossumb6775db1994-08-01 11:34:53 +0000100 if ( v < 0 || v >= FD_SETSIZE ) {
101 err_setstr(ValueError, "filedescriptor out of range in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +0000102 return -1;
103 }
104 if ( v > max ) max = v;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000105#endif
Guido van Rossumed233a51992-06-23 09:07:03 +0000106 FD_SET(v, set);
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000107 /* add object and its file descriptor to the list */
108 if ( index >= FD_SETSIZE ) {
109 err_setstr(ValueError, "too many file descriptors in select()");
110 return -1;
111 }
112 fd2obj[index].obj = o;
113 fd2obj[index].fd = v;
114 fd2obj[++index].obj = (object *)0; /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000115 }
116 return max+1;
117}
118
119static object *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000120set2list(set, fd2obj)
Guido van Rossumed233a51992-06-23 09:07:03 +0000121 fd_set *set;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000122 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000123{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000124 int j, num=0;
Guido van Rossumed233a51992-06-23 09:07:03 +0000125 object *list, *o;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000126 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000127
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000128 for(j=0; fd2obj[j].obj; j++)
129 if ( FD_ISSET(fd2obj[j].fd, set) )
Guido van Rossumed233a51992-06-23 09:07:03 +0000130 num++;
131 list = newlistobject(num);
132 num = 0;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000133 for(j=0; fd2obj[j].obj; j++) {
134 fd = fd2obj[j].fd;
135 if ( FD_ISSET(fd, set) ) {
136#ifndef _MSC_VER
137 if ( fd > FD_SETSIZE ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000138 err_setstr(SystemError,
139 "filedescriptor out of range returned in select()");
Guido van Rossumed233a51992-06-23 09:07:03 +0000140 return NULL;
141 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000142#endif
143 o = fd2obj[j].obj;
Guido van Rossumed233a51992-06-23 09:07:03 +0000144 INCREF(o);
145 setlistitem(list, num, o);
146 num++;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000147 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000148 }
149 return list;
150}
151
152static object *
153select_select(self, args)
154 object *self;
155 object *args;
156{
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000157 pylist rfd2obj[FD_SETSIZE + 3], wfd2obj[FD_SETSIZE + 3], efd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000158 object *ifdlist, *ofdlist, *efdlist;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000159 object *ret, *tout;
Guido van Rossumed233a51992-06-23 09:07:03 +0000160 fd_set ifdset, ofdset, efdset;
161 double timeout;
162 struct timeval tv, *tvp;
163 int seconds;
164 int imax, omax, emax, max;
165 int n;
166
167
168 /* Get args. Looks funny because of optional timeout argument */
Guido van Rossumc7a22701993-11-01 16:27:16 +0000169 if ( getargs(args, "(OOOO)", &ifdlist, &ofdlist, &efdlist, &tout) ) {
Guido van Rossumc7a22701993-11-01 16:27:16 +0000170 if (tout == None)
171 tvp = (struct timeval *)0;
172 else {
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000173 if (!getargs(tout, "d;timeout must be float or None", &timeout))
Guido van Rossumc7a22701993-11-01 16:27:16 +0000174 return NULL;
Sjoerd Mullender78ed4201993-11-02 15:34:23 +0000175 seconds = (int)timeout;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000176 timeout = timeout - (double)seconds;
177 tv.tv_sec = seconds;
178 tv.tv_usec = (int)(timeout*1000000.0);
179 tvp = &tv;
180 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000181 } else {
182 /* Doesn't have 4 args, that means no timeout */
183 err_clear();
184 if (!getargs(args, "(OOO)", &ifdlist, &ofdlist, &efdlist) )
185 return 0;
186 tvp = (struct timeval *)0;
187 }
188 if ( !is_listobject(ifdlist) || !is_listobject(ofdlist) ||
189 !is_listobject(efdlist) ) {
190 err_badarg();
191 return 0;
192 }
193
Guido van Rossumed233a51992-06-23 09:07:03 +0000194 /* Convert lists to fd_sets, and get maximum fd number */
Guido van Rossum07432c01995-03-29 16:47:45 +0000195 if( (imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000196 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000197 if( (omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000198 return 0;
Guido van Rossum07432c01995-03-29 16:47:45 +0000199 if( (emax=list2set(efdlist, &efdset, efd2obj)) < 0 )
Guido van Rossumed233a51992-06-23 09:07:03 +0000200 return 0;
201 max = imax;
202 if ( omax > max ) max = omax;
203 if ( emax > max ) max = emax;
204
Guido van Rossumff4949e1992-08-05 19:58:53 +0000205 BGN_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000206 n = select(max, &ifdset, &ofdset, &efdset, tvp);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000207 END_SAVE
Guido van Rossumed233a51992-06-23 09:07:03 +0000208
209 if ( n < 0 ) {
210 err_errno(SelectError);
211 return 0;
212 }
213
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000214 if ( n == 0 ) { /* Speedup hack */
215 ifdlist = newlistobject(0);
216 ret = mkvalue("OOO", ifdlist, ifdlist, ifdlist);
217 XDECREF(ifdlist);
218 return ret;
219 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000220
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000221 ifdlist = set2list(&ifdset, rfd2obj);
222 ofdlist = set2list(&ofdset, wfd2obj);
223 efdlist = set2list(&efdset, efd2obj);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000224 ret = mkvalue("OOO", ifdlist, ofdlist, efdlist);
225 XDECREF(ifdlist);
226 XDECREF(ofdlist);
227 XDECREF(efdlist);
228 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000229}
230
231
232static struct methodlist select_methods[] = {
233 { "select", select_select },
234 { 0, 0 },
235};
236
237
238void
239initselect()
240{
241 object *m, *d;
242 m = initmodule("select", select_methods);
243 d = getmoduledict(m);
244 SelectError = newstringobject("select.error");
245 if ( SelectError == NULL || dictinsert(d, "error", SelectError) )
246 fatal("Cannot define select.error");
247}