Re: MinGW patch

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: MinGW patch

Paolo Bonzini

> 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
Reply | Threaded
Open this post in threaded view
|

RE: MinGW patch

Akeroyd, FA (Freddie)
> 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
Reply | Threaded
Open this post in threaded view
|

Re: RE: MinGW patch

Paolo Bonzini
> * 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
Reply | Threaded
Open this post in threaded view
|

RE: RE: MinGW patch

Akeroyd, FA (Freddie)

> 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
Reply | Threaded
Open this post in threaded view
|

Re: RE: MinGW patch

Paolo Bonzini

> 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
Reply | Threaded
Open this post in threaded view
|

RE: RE: MinGW patch

Akeroyd, FA (Freddie)
> > 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