Skip to content

Commit 0a18a9d

Browse files
committed
A add much more useful select(2) implementation than is provided by
windows sockets. The winsock implementation will only work with sockets; our implementation works with sockets and file descriptors. By association, stream_select() will now operate correctly with files, pipes and sockets. This change required linking against the winsock2 library. In terms of compatibility, only older versions of windows 95 do not have winsock2 installed by default. It is available as a redistributable file, and is most likely installed by any OS patches (eg: Internet Explorer) applied by the user. Also, add a win32 compatible pipe test when opening a stream from a pipe. This test will only work on NT, win2k and XP platforms. Without this test, interleaved fread() and select() calls would cause the read buffer to be clobbered. I will be working on a fix for this issue for win9x.
1 parent 5edec2a commit 0a18a9d

30 files changed

+225
-43
lines changed

ext/curl/interface.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include <string.h>
3131

3232
#ifdef PHP_WIN32
33-
#include <winsock.h>
33+
#include <winsock2.h>
3434
#include <sys/types.h>
3535
#endif
3636

ext/curl/streams.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include <string.h>
3737

3838
#ifdef PHP_WIN32
39-
#include <winsock.h>
39+
#include <winsock2.h>
4040
#include <sys/types.h>
4141
#endif
4242

ext/fbsql/php_fbsql.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#include "ext/standard/php_string.h"
4444

4545
#ifdef PHP_WIN32
46-
#include <winsock.h>
46+
#include <winsock2.h>
4747
#else
4848
#include <php_config.h>
4949

ext/ftp/ftp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include <string.h>
3434
#include <time.h>
3535
#ifdef PHP_WIN32
36-
#include <winsock.h>
36+
#include <winsock2.h>
3737
#elif defined(NETWARE)
3838
#ifdef USE_WINSOCK /* Modified to use Winsock (NOVSOCK2.H), atleast for now */
3939
#include <novsock2.h>

ext/hyperwave/hg_comm.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include <string.h>
3232
#include <sys/types.h>
3333
#ifdef PHP_WIN32
34-
# include <winsock.h>
34+
# include <winsock2.h>
3535
# define EWOULDBLOCK WSAEWOULDBLOCK
3636
# define ETIMEDOUT WSAETIMEDOUT
3737
# define bcopy memcpy

ext/hyperwave/hw.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "SAPI.h"
3535

3636
#ifdef PHP_WIN32
37-
#include <winsock.h>
37+
#include <winsock2.h>
3838
#endif
3939

4040
#if HYPERWAVE

ext/imap/php_imap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#include <signal.h>
5151

5252
#ifdef PHP_WIN32
53-
#include <winsock.h>
53+
#include <winsock2.h>
5454
#include <stdlib.h>
5555
#include "win32/sendmail.h"
5656
MAILSTREAM DEFAULTPROTO;

ext/ldap/ldap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#ifdef PHP_WIN32
4747
#include <string.h>
4848
#if HAVE_NSLDAP
49-
#include <winsock.h>
49+
#include <winsock2.h>
5050
#endif
5151
#define strdup _strdup
5252
#undef WINDOWS

ext/mcal/php_mcal.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#include "ext/standard/info.h"
4343
#include "ext/standard/basic_functions.h"
4444
#ifdef PHP_WIN32
45-
#include "winsock.h"
45+
#include "winsock2.h"
4646
#endif
4747

4848
static void cal_close_it(zend_rsrc_list_entry *rsrc TSRMLS_DC);

ext/mysql/php_mysql.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#if HAVE_MYSQL
3838

3939
#ifdef PHP_WIN32
40-
# include <winsock.h>
40+
# include <winsock2.h>
4141
# define signal(a, b) NULL
4242
#elif defined(NETWARE)
4343
# include <sys/socket.h>

ext/odbc/php_odbc.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#include "php_ini.h"
4545

4646
#ifdef PHP_WIN32
47-
#include <winsock.h>
47+
#include <winsock2.h>
4848

4949
#define ODBC_TYPE "Win32"
5050
#define PHP_ODBC_TYPE ODBC_TYPE

ext/rpc/com/com_wrapper.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@
5656

5757
#define _WIN32_DCOM
5858

59+
#include "php.h"
60+
#include "php_ini.h"
61+
5962
#include <iostream.h>
6063
#include <math.h>
6164
#include <ocidl.h>
6265

63-
#include "php.h"
64-
#include "php_ini.h"
65-
6666
#include "../rpc.h"
6767
#include "../php_rpc.h"
6868
#include "../handler.h"

ext/snmp/snmp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
#include <sys/types.h>
3535
#ifdef PHP_WIN32
36-
#include <winsock.h>
36+
#include <winsock2.h>
3737
#include <errno.h>
3838
#include <process.h>
3939
#include "win32/time.h"

ext/standard/dns.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#include "resolv.h"
4545
#endif
4646
#endif /* HAVE_LIBBIND */
47-
#include <winsock.h>
47+
#include <winsock2.h>
4848
#else /* This holds good for NetWare too, both for Winsock and Berkeley sockets */
4949
#include <netinet/in.h>
5050
#if HAVE_ARPA_INET_H

ext/standard/file.c

+158-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#include <fcntl.h>
4545
#ifdef PHP_WIN32
4646
#include <windows.h>
47-
#include <winsock.h>
47+
#include <winsock2.h>
4848
#define O_RDONLY _O_RDONLY
4949
#include "win32/param.h"
5050
#include "win32/winutil.h"
@@ -821,6 +821,160 @@ static int stream_array_emulate_read_fd_set(zval *stream_array TSRMLS_DC)
821821
}
822822
/* }}} */
823823

824+
#ifdef PHP_WIN32
825+
/* Win32 select() will only work with sockets, so we roll our own implementation that will
826+
* get the OS file handle from regular fd's and sockets and then use WaitForMultipleObjects().
827+
* This implementation is not as feature-full as posix select, but it works for our purposes
828+
*/
829+
static int php_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
830+
{
831+
HANDLE *handles;
832+
DWORD ms, waitret;
833+
DWORD ms_total;
834+
int i, f, s, fd_count = 0, sock_count = 0;
835+
int retval;
836+
fd_set ard, awr, aex; /* active fd sets */
837+
long sock_events;
838+
839+
for (i = 0; i < max_fd; i++) {
840+
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
841+
if (_get_osfhandle(i) == 0xffffffff) {
842+
/* it is a socket */
843+
sock_count++;
844+
} else {
845+
fd_count++;
846+
}
847+
}
848+
}
849+
850+
if (fd_count + sock_count == 0) {
851+
return 0;
852+
}
853+
854+
handles = (HANDLE*)emalloc((fd_count + sock_count) * sizeof(HANDLE));
855+
856+
/* populate the events and handles arrays */
857+
f = 0;
858+
s = 0;
859+
for (i = 0; i < max_fd; i++) {
860+
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
861+
long h = _get_osfhandle(i);
862+
if (h == 0xFFFFFFFF) {
863+
HANDLE evt;
864+
long evt_flags = 0;
865+
866+
if (FD_ISSET(i, rfds)) {
867+
evt_flags |= FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE;
868+
}
869+
if (FD_ISSET(i, wfds)) {
870+
evt_flags |= FD_WRITE;
871+
}
872+
if (FD_ISSET(i, efds)) {
873+
evt_flags |= FD_OOB;
874+
}
875+
876+
evt = WSACreateEvent();
877+
WSAEventSelect(i, evt, evt_flags);
878+
879+
handles[fd_count + s] = evt;
880+
s++;
881+
} else {
882+
handles[f++] = (HANDLE)h;
883+
}
884+
}
885+
}
886+
887+
/* calculate how long we need to wait in milliseconds */
888+
if (tv == NULL) {
889+
ms_total = INFINITE;
890+
} else {
891+
ms_total = tv->tv_sec * 1000;
892+
ms_total += tv->tv_usec / 1000;
893+
}
894+
895+
waitret = MsgWaitForMultipleObjects(fd_count + sock_count, handles, FALSE, ms_total, QS_ALLEVENTS);
896+
897+
if (waitret == WAIT_TIMEOUT) {
898+
retval = 0;
899+
} else if (waitret == 0xFFFFFFFF) {
900+
retval = -1;
901+
} else {
902+
903+
FD_ZERO(&ard);
904+
FD_ZERO(&awr);
905+
FD_ZERO(&aex);
906+
907+
f = 0;
908+
retval = 0;
909+
for (i = 0; i < max_fd; i++) {
910+
if (FD_ISSET(i, rfds) || FD_ISSET(i, wfds) || FD_ISSET(i, efds)) {
911+
if (f >= fd_count) {
912+
/* socket event */
913+
HANDLE evt = handles[f];
914+
915+
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
916+
/* check for various signal states */
917+
if (FD_ISSET(i, rfds)) {
918+
WSAEventSelect(i, evt, FD_READ|FD_CONNECT|FD_ACCEPT|FD_CLOSE);
919+
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
920+
FD_SET(i, &ard);
921+
}
922+
}
923+
if (FD_ISSET(i, wfds)) {
924+
WSAEventSelect(i, evt, FD_WRITE);
925+
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
926+
FD_SET(i, &awr);
927+
}
928+
}
929+
if (FD_ISSET(i, efds)) {
930+
WSAEventSelect(i, evt, FD_OOB);
931+
if (WAIT_OBJECT_0 == WaitForSingleObject(evt, 0)) {
932+
FD_SET(i, &aex);
933+
}
934+
}
935+
retval++;
936+
}
937+
938+
WSACloseEvent(evt);
939+
940+
} else {
941+
if (WAIT_OBJECT_0 == WaitForSingleObject(handles[f], 0)) {
942+
if (FD_ISSET(i, rfds)) {
943+
FD_SET(i, &ard);
944+
}
945+
if (FD_ISSET(i, wfds)) {
946+
FD_SET(i, &awr);
947+
}
948+
if (FD_ISSET(i, efds)) {
949+
FD_SET(i, &aex);
950+
}
951+
retval++;
952+
}
953+
954+
}
955+
f++;
956+
}
957+
}
958+
959+
if (rfds) {
960+
*rfds = ard;
961+
}
962+
if (wfds) {
963+
*wfds = awr;
964+
}
965+
if (efds) {
966+
*efds = aex;
967+
}
968+
}
969+
970+
efree(handles);
971+
972+
return retval;
973+
}
974+
#else
975+
#define php_select(m, r, w, e, t) select(m, r, w, e, t)
976+
#endif
977+
824978
/* {{{ proto int stream_select(array &read_streams, array &write_streams, array &except_streams, int tv_sec[, int tv_usec])
825979
Runs the select() system call on the sets of streams with a timeout specified by tv_sec and tv_usec */
826980
PHP_FUNCTION(stream_select)
@@ -867,11 +1021,11 @@ PHP_FUNCTION(stream_select)
8671021
}
8681022
}
8691023

870-
retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
1024+
retval = php_select(max_fd+1, &rfds, &wfds, &efds, tv_p);
8711025

8721026
if (retval == -1) {
873-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s",
874-
errno, strerror(errno));
1027+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
1028+
errno, strerror(errno), max_fd);
8751029
RETURN_FALSE;
8761030
}
8771031

ext/standard/fsock.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#include <sys/socket.h>
4747
#endif
4848
#ifdef PHP_WIN32
49-
#include <winsock.h>
49+
#include <winsock2.h>
5050
#elif defined(NETWARE)
5151
#ifdef NEW_LIBC
5252
#ifdef USE_WINSOCK

ext/standard/ftp_fopen_wrapper.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
#ifdef PHP_WIN32
3434
#include <windows.h>
35-
#include <winsock.h>
35+
#include <winsock2.h>
3636
#define O_RDONLY _O_RDONLY
3737
#include "win32/param.h"
3838
#elif defined(NETWARE)
@@ -55,7 +55,7 @@
5555
#endif
5656

5757
#ifdef PHP_WIN32
58-
#include <winsock.h>
58+
#include <winsock2.h>
5959
#elif defined(NETWARE) && defined(USE_WINSOCK)
6060
/*#include <ws2nlm.h>*/
6161
#include <novsock2.h>

ext/standard/http_fopen_wrapper.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
#ifdef PHP_WIN32
3838
#include <windows.h>
39-
#include <winsock.h>
39+
#include <winsock2.h>
4040
#define O_RDONLY _O_RDONLY
4141
#include "win32/param.h"
4242
#elif defined(NETWARE)
@@ -59,7 +59,7 @@
5959
#endif
6060

6161
#ifdef PHP_WIN32
62-
#include <winsock.h>
62+
#include <winsock2.h>
6363
#elif defined(NETWARE) && defined(USE_WINSOCK)
6464
/*#include <ws2nlm.h>*/
6565
#include <novsock2.h>

ext/standard/pack.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include <fcntl.h>
2828
#ifdef PHP_WIN32
2929
#include <windows.h>
30-
#include <winsock.h>
30+
#include <winsock2.h>
3131
#define O_RDONLY _O_RDONLY
3232
#include "win32/param.h"
3333
#elif defined(NETWARE)

ext/zlib/zlib.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include <fcntl.h>
3737
#ifdef PHP_WIN32
3838
#include <windows.h>
39-
#include <winsock.h>
39+
#include <winsock2.h>
4040
#define O_RDONLY _O_RDONLY
4141
#include "win32/param.h"
4242
#else

main/fopen_wrappers.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
#ifdef PHP_WIN32
3535
#include <windows.h>
36-
#include <winsock.h>
36+
#include <winsock2.h>
3737
#define O_RDONLY _O_RDONLY
3838
#include "win32/param.h"
3939
#elif defined(NETWARE)
@@ -74,7 +74,7 @@
7474
#endif
7575

7676
#ifdef PHP_WIN32
77-
#include <winsock.h>
77+
#include <winsock2.h>
7878
#elif defined(NETWARE) && defined(USE_WINSOCK)
7979
/*#include <ws2nlm.h>*/
8080
#include <novsock2.h>

0 commit comments

Comments
 (0)