00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00033 #include "plibc_private.h"
00034
00047 int _win_select(int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds,
00048 const struct timeval *tv)
00049 {
00050 DWORD ms_total, limit;
00051 HANDLE handles[MAXIMUM_WAIT_OBJECTS], hPipes[MAXIMUM_WAIT_OBJECTS];
00052 int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
00053 int n_handles, i, iPipes;
00054 fd_set sock_read, sock_write, sock_except;
00055 fd_set aread, awrite, aexcept;
00056 int sock_max_fd;
00057 struct timeval tvslice;
00058 int retcode;
00059
00060 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
00061
00062 n_handles = 0;
00063 sock_max_fd = -1;
00064 iPipes = 0;
00065
00066
00067 if(tv == NULL)
00068 ms_total = INFINITE;
00069 else
00070 {
00071 ms_total = tv->tv_sec * 1000;
00072 ms_total += tv->tv_usec / 1000;
00073 }
00074
00075
00076 if (!(rfds || wfds || efds))
00077 {
00078 Sleep(ms_total);
00079
00080 return 0;
00081 }
00082
00083 FD_ZERO(&sock_read);
00084 FD_ZERO(&sock_write);
00085 FD_ZERO(&sock_except);
00086
00087
00088 for(i = 0; i < max_fd; i++)
00089 {
00090 if(SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) ||
00091 SAFE_FD_ISSET(i, efds))
00092 {
00093 unsigned long ulVal;
00094
00095 if (ioctlsocket(i, FIONREAD, &ulVal) != SOCKET_ERROR && _get_osfhandle(i) == -1)
00096 {
00097
00098 if(SAFE_FD_ISSET(i, rfds))
00099 FD_SET(i, &sock_read);
00100
00101 if(SAFE_FD_ISSET(i, wfds))
00102 FD_SET(i, &sock_write);
00103
00104 if(SAFE_FD_ISSET(i, efds))
00105 FD_SET(i, &sock_except);
00106
00107 if(i > sock_max_fd)
00108 sock_max_fd = i;
00109 }
00110 else
00111 {
00112 if (GetFileType((HANDLE) i) == FILE_TYPE_PIPE)
00113 hPipes[iPipes++] = (HANDLE) i;
00114 else
00115 {
00116 handles[n_handles] = (HANDLE) _get_osfhandle(i);
00117 if ((DWORD) handles[n_handles] == 0xffffffff)
00118 handles[n_handles] = (HANDLE) i;
00119 handle_slot_to_fd[n_handles] = i;
00120 n_handles++;
00121 }
00122 }
00123 }
00124 }
00125
00126 if((n_handles == 0) && (iPipes == 0))
00127 {
00128
00129 return select(max_fd, rfds, wfds, efds, tv);
00130 }
00131
00132
00133
00134
00135 FD_ZERO(&aread);
00136 FD_ZERO(&awrite);
00137 FD_ZERO(&aexcept);
00138
00139 limit = GetTickCount() + ms_total;
00140 do
00141 {
00142 retcode = 0;
00143
00144 if(sock_max_fd >= 0)
00145 {
00146
00147
00148 aread = sock_read;
00149 awrite = sock_write;
00150 aexcept = sock_except;
00151
00152 tvslice.tv_sec = 0;
00153 tvslice.tv_usec = 100000;
00154
00155 if ((retcode = select(sock_max_fd + 1, &aread, &awrite, &aexcept,
00156 &tvslice)) == SOCKET_ERROR)
00157 {
00158 SetErrnoFromWinsockError(WSAGetLastError());
00159
00160 return -1;
00161 }
00162 }
00163
00164 if(n_handles > 0)
00165 {
00166
00167 DWORD wret;
00168
00169 wret =
00170 MsgWaitForMultipleObjects(n_handles, handles, FALSE,
00171 retcode > 0 ? 0 : 100, QS_ALLEVENTS);
00172
00173 if(wret == WAIT_TIMEOUT)
00174 {
00175
00176
00177
00178
00179 ;
00180 }
00181 else if(wret == WAIT_FAILED)
00182 {
00183 SetErrnoFromWinError(GetLastError());
00184
00185 return -1;
00186 }
00187 else
00188 {
00189 for(i = 0; i < n_handles; i++)
00190 {
00191 if(WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0))
00192 {
00193 if(SAFE_FD_ISSET(handle_slot_to_fd[i], rfds))
00194 {
00195 FD_SET(handle_slot_to_fd[i], &aread);
00196 }
00197
00198 if(SAFE_FD_ISSET(handle_slot_to_fd[i], wfds))
00199 FD_SET(handle_slot_to_fd[i], &awrite);
00200
00201 if(SAFE_FD_ISSET(handle_slot_to_fd[i], efds))
00202 FD_SET(handle_slot_to_fd[i], &aexcept);
00203
00204 retcode++;
00205 }
00206 }
00207 }
00208 }
00209
00210
00211 for(i = 0; i < iPipes; i++)
00212 {
00213 DWORD dwBytes;
00214 if(SAFE_FD_ISSET(hPipes[i], rfds))
00215 {
00216 if (! PeekNamedPipe(hPipes[i], NULL, 0, NULL, &dwBytes, NULL))
00217 {
00218 retcode = -1;
00219 SetErrnoFromWinError(GetLastError());
00220 }
00221 else if (dwBytes)
00222 {
00223 FD_SET((int) hPipes[i], &aread);
00224 retcode++;
00225 }
00226 }
00227 else if (SAFE_FD_ISSET(hPipes[i], wfds) || SAFE_FD_ISSET(hPipes[i], efds))
00228 {
00229 errno = ENOSYS;
00230 return -1;
00231 }
00232 }
00233 }
00234 while(retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
00235
00236 if(rfds)
00237 *rfds = aread;
00238
00239 if(wfds)
00240 *wfds = awrite;
00241
00242 if(efds)
00243 *efds = aexcept;
00244
00245 return retcode;
00246 }