> I haven't traced the quit.st problem as yet. If I comment out the call > to send the "aboutToQuit" message in VMpr_ObjectMemory_quit() it works > OK; when the line is present the "Execution begins..." output is lost > and so the test fails. I've stepped through the lines in gdb but no > crash/errors are reported and it gets to exit(arg1) OK. Adding a > _flushall() call before sending "aboutToQuit" makes the output appear on > the screen, but adding one after the call does not, so it would appear > that the output is removed while "aboutToQuit" is being processed. Close enough: files are closed during the #aboutToQuit. I'll think more about it (it does not seem to bad to just add a AC_CHECK_FUNCS(_flushall) and add the _flushall where you suggest, or maybe we could add a more standard "fflush(stdout);fflush(stderr);"?). I reorganized your win_utils.[ch] around the preexisting socketx.h header. Could you test this patch (which does not include your kernel/* changes)? Paolo --- orig/lib-src/Makefile.am +++ mod/lib-src/Makefile.am @@ -6,7 +6,7 @@ library_la_DEPENDENCIES = @LTLIBOBJS@ @ # These are to be included *always*, the rest are driven by configure.in library_la_SOURCES = \ qsort.c getopt.c getopt1.c md5.c avltrees.c rbtrees.c \ - strspell.c signalx.c ltdl.c regex.c + strspell.c signalx.c ltdl.c regex.c socketx.c noinst_HEADERS = \ obstack.h poll_.h getopt.h md5.h ansidecl.h strspell.h \ --- orig/lib-src/poll.c +++ mod/lib-src/poll.c @@ -25,8 +25,7 @@ #include "poll.h" #include <errno.h> #include <limits.h> -#include <sys/socket.h> -#include <sys/select.h> +#include "socketx.h" #include <unistd.h> #ifdef HAVE_SYS_IOCTL_H --- orig/lib-src/socketx.h +++ mod/lib-src/socketx.h @@ -56,10 +56,51 @@ #ifdef HAVE_INET_SOCKETS #ifdef __MSVCRT__ +#include <windows.h> #include <winsock2.h> +#include <io.h> + #define is_socket_error(err) (WSAGetLastError() == WSA##err) #define clear_socket_error() WSASetLastError(0) + +#define ESHUTDOWN WSAESHUTDOWN +#define ENOTCONN WSAENOTCONN +#define ECONNRESET WSAECONNRESET +#define ECONNABORTED WSAECONNABORTED +#define ENETRESET WSAENETRESET + +typedef int nfds_t; + +/* re-define FD_ISSET to avoid a WSA call while we are not using + * network sockets */ +#undef FD_ISSET +#define FD_ISSET(fd, set) win_fd_isset(fd, set) + +static inline int +win_fd_isset (int fd, fd_set * set) +{ + int i; + if (set == NULL) + return 0; + + for (i = 0; i < set->fd_count; i++) + if (set->fd_array[i] == fd) + return 1; + + return 0; +} + +int win_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *ptv); +int win_recv(int fd, void* buffer, int n, int flags); + +#undef select +#define select win_select + +#undef recv +#define recv win_recv + #else /* !__MSVCRT__ */ + #include <errno.h> #include <sys/select.h> #include <sys/socket.h> * added files --- /dev/null +++ mod/lib-src/socketx.c @@ -0,0 +1,151 @@ +/* socketx.c - Extend WinSock functions to handle other objects than sockets + Contributed by Freddie Akeroyd. + + Copyright 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include <socketx.h> + +#ifdef __MSVCRT__ +#include <stdio.h> +#include <conio.h> + +#define MAX_WIN_HANDLES 300 /* max number of fd we can handle */ + +/* n = maxfd + 1 */ +int +win_select (int n, fd_set * rfds, fd_set * wfds, fd_set * efds, + struct timeval *ptv) +{ + HANDLE handle_array[MAX_WIN_HANDLES]; + int handle_fd[MAX_WIN_HANDLES]; + fd_set *handle_set[MAX_WIN_HANDLES]; + DWORD ret, ret0, wait_timeout, nhandles; + int i, nset; + BOOL bRet; + MSG msg; + + _flushall (); + nhandles = 0; + for (i = 0; i < n; i++) + { + if ((efds != NULL) && FD_ISSET (i, efds)) + FD_CLR (i, efds); /* assume no exceptions */ + + if ((wfds != NULL) && FD_ISSET (i, wfds)) + { + handle_array[nhandles] = (HANDLE) _get_osfhandle (i); + handle_fd[nhandles] = i; + handle_set[nhandles] = wfds; + nhandles++; + FD_CLR (i, wfds); /* we will set it later if there is output */ + } + + if ((rfds != NULL) && FD_ISSET (i, rfds)) + { + handle_array[nhandles] = (HANDLE) _get_osfhandle (i); + handle_fd[nhandles] = i; + handle_set[nhandles] = rfds; + nhandles++; + FD_CLR (i, rfds); /* we will set it later if there is input */ + } + } + + if (ptv == NULL) + wait_timeout = INFINITE; + else + wait_timeout = ptv->tv_sec * 1000 + ptv->tv_usec / 1000; + + for (;;) + { + ret = + MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, + wait_timeout, QS_ALLINPUT); + ret0 = ret - WAIT_OBJECT_0; + if (ret0 != nhandles) + break; + + /* new input of some other kind */ + while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + + /* now do a quick poll of all handles to see how many are ready */ + nset = 0; + for (i = 0; i < nhandles; i++) + { + ret = WaitForSingleObject (handle_array[i], 0); + if (ret == WAIT_OBJECT_0) + { + FD_SET (handle_fd[i], handle_set[i]); + nset++; + } + } + + return nset; +} + +/* + * This only gets called with the MSG_PEEK flag by poll.c when a read is ready + * It does not need to indicate the real + * number of characters available ... only return values of 1 and 0 + * are currently tested for by poll.c + * TODO: return real number of characters available + */ +int +win_recv (int fd, void *buffer, int n, int flags) +{ + BOOL bRet; + int i, ret, data_available; + size_t nread; + INPUT_RECORD *irbuffer; + DWORD nevents, nbuffer; + HANDLE h = (HANDLE) _get_osfhandle (fd); + ret = WaitForSingleObject (h, 0); + if (ret == WAIT_OBJECT_0) + data_available = 1; + else + data_available = 0; + + if (flags != MSG_PEEK) + return 0; + + /* MSG_PEEK */ + if (GetFileType (h) != FILE_TYPE_CHAR) + return (data_available ? 1 : 0); + + /* console (FILE_TYPE_CHAR) */ + nbuffer = nevents = 0; + bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); + if (!bRet || nbuffer == 0) + return 0; + + irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); + bRet = PeekConsoleInput (h, irbuffer, nbuffer, &nevents); + if (!bRet || nevents == 0) + return 0; + + nread = 0; + for (i = 0; i < nevents; i++) + if (irbuffer[i].EventType == KEY_EVENT) + nread++; + + return nread; +} +#endif _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> Close enough: files are closed during the #aboutToQuit. I'll think
more > about it (it does not seem to bad to just add a > AC_CHECK_FUNCS(_flushall) and add the _flushall where you suggest, or > maybe we could add a more standard "fflush(stdout);fflush(stderr);"?). "fflush(stdout);fflush(stderr);" or "fflush(NULL);" both do the job. Looking more at the code I see "aboutToQuit" closes the low level fd, so any unflushed data written via the stdout FILE pointer by e.g. printf gets lost. All Smalltalk file I/O looks like it goes via an fd, so I think stdout (maybe stderr too, but I believe that is usually unbuffered) is probably the only one that needs catching. > I reorganized your win_utils.[ch] around the preexisting socketx.h > header. Could you test this patch (which does not include your kernel/* > changes)? The patch works fine with a couple of minor tweaks: * socketx.c needs to include config.h as socketx.h uses HAVE_INET_SOCKETS * There is an issue with build-aux/inet.m4 The MinGW libwsock32.a only exports __stdcall decorated names (listen@8 etc) and so the test there does not detect it. I enclose a possible patch for this. * I stared getting alloc.h:76: warning: declaration does not declare anything and alloc.c failed to compile. I traced the problem to a definition in rpcndr.h which is included by winsock.h and does #define small char Adding #undef small To alloc.h fixed this Regards, Freddie -----Original Message----- From: Paolo Bonzini [mailto:[hidden email]] Sent: 02 July 2007 19:56 To: Akeroyd, FA (Freddie); GNU Smalltalk Subject: Re: MinGW patch > I haven't traced the quit.st problem as yet. If I comment out the call > to send the "aboutToQuit" message in VMpr_ObjectMemory_quit() it works > OK; when the line is present the "Execution begins..." output is lost > and so the test fails. I've stepped through the lines in gdb but no > crash/errors are reported and it gets to exit(arg1) OK. Adding a > _flushall() call before sending "aboutToQuit" makes the output appear on > the screen, but adding one after the call does not, so it would appear > that the output is removed while "aboutToQuit" is being processed. I reorganized your win_utils.[ch] around the preexisting socketx.h header. Could you test this patch (which does not include your kernel/* changes)? Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk mingw-inet.patch (1K) Download Attachment |
> * socketx.c needs to include config.h as socketx.h uses
> HAVE_INET_SOCKETS Okay. > * There is an issue with build-aux/inet.m4 The MinGW libwsock32.a only > exports __stdcall decorated names (listen@8 etc) and so the test there > does not detect it. I enclose a possible patch for this. I just moved your test in place of the old AC_CHECK_LIB. > * I stared getting > alloc.h:76: warning: declaration does not declare anything > and alloc.c failed to compile. I traced the problem to a definition in > rpcndr.h which is included by winsock.h and does Indeed alloc.c already had a workaround for this. I moved it up from alloc.c to alloc.h. If you have time, could you improve win_recv so that it works for sockets and pipes, as well as restoring support for the third set in win_select? (Long term, it's probably just better to merge win_select and win_recv into a Windows-specific implementation of poll, but for now let's keep your solution). Thanks! Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> If you have time, could you improve win_recv so that it works for > sockets and pipes, as well as restoring support for the third set in > win_select? (Long term, it's probably just better to merge win_select > and win_recv into a Windows-specific implementation of poll, but for now > let's keep your solution). Socket support on windows may need a bit more work as descriptors returned by socket() and fd's returned by open() can, in principle, clash. In the Microsoft implementation of the Winsock API socket descriptors are related to windows file handles and you can use _open_osfhandle() and related functions to allocate a C RTL file descriptor to work with. This would take care of keeping the numbers unique, but I'm not sure if all of the usual CRTL functions work as expected with these. We may need to keep a separate list of all socket CRTL fd we generate and so lookup the fd later and treat sockets differently on a read/write call etc. If we end up doing this lookup, then it would be more general to create dummy fd's via e.g. open("/dev/null") for our book keeping as we are not then relying on a Microsoft implementation of the Winsock API. I was wondering if GNU Smalltalk preserves the identity of socket and file descriptors inside its instances and so only calls recv()/send() on sockets and read()/write() on CRTL file descriptors? If so that will make life easier and we only need to handle poll() as you mention above. Freddie _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> Socket support on windows may need a bit more work as descriptors > returned by socket() and fd's returned by open() can, in principle, > clash. I'm not sure this is true -- on Unix, they are the same `beast' and, on Windows, we can... > use _open_osfhandle() and related functions to allocate a C RTL file > descriptor to work with. While other functions will not work, we can have wrappers on recvfrom/sendto that unbox the Windows handle and call the winsock function. > I was wondering if GNU Smalltalk preserves the identity of socket and > file descriptors inside its instances and so only calls recv()/send() on > sockets and read()/write() on CRTL file descriptors? It does (this was done as part of a half-hearted mingw port a few years ago, that introduced socketx.h as you found it). Paolo _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
> > Socket support on windows may need a bit more work as descriptors
> > returned by socket() and fd's returned by open() can, in principle, > > clash. > I'm not sure this is true -- on Unix, they are the same `beast' and, on > Windows, we can... > > use _open_osfhandle() and related functions to allocate a C RTL file > > descriptor to work with. Yes, _open_osfhandle() will generate a unique number for you. When I said "clash" I was only referring to the initial numbers returned by socket() and open() which can overlap. > While other functions will not work, we can have wrappers > on recvfrom/sendto that unbox the Windows handle and call the > winsock function. That seems a good approach and should work fine as GNU Smalltalk keeps socket descriptors and file descriptors separate as you mentioned. I will try to have a play with it, time permitting, over the next few weeks. Thanks for all your help with the MinGW porting and have a good trip to Montreal Freddie _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |