[GRASS5] display system

I've been looking into the problems with mon.start/XDRIVER which
necessitated the code which is conditionalised upon "#ifdef __W98__",
and have a few comments.

1. The problem seems to be specific to XDRIVER; the CELL driver works
fine if mon.start and src/display/devices/lib are build without
__W98__ defined.

2. The above makes sense; the Windows resources (e.g. the window)
created by Graph_Set() presumably aren't going to be inherited across
the fork() (certainly, POSIX/XPG*/Unix98 don't say anything about the
behaviour of fork() w.r.t. Windows resources).

3. This would apply equally to a "native" Windows or MacOS driver. X
is rather different because of X11's client-server architecture; the
only system resource held by an X client is the descriptor for the
connection to the X server.

4. Intuition says that __W98__ ought to be unnecessary when using the
vanilla XDRIVER under Cygwin with an X server. There have been
reported problems, although this could be a bug in Cygwin or Cygwin's
Xlib. Hard information would be welcome.

5. The existing (problematic) behaviour exists for a reason. Delaying
the "daemon-isation" (fork(), parent exit()s) until everything has
been initialised and the monitor is ready to accept connections
ensures that the monitor is ready as soon as mon.start terminates.

This ensures that the subsequent invocation of mon.select will succeed
even when mon.select is run immediately afterwards. It also explains
why, with the libW11 port, the first attempt to select the monitor
fails (and, if the initialisation were to take too long, the second
attempt would also fail).

So what, if anything, should we do about it?

One option would be to create the socket (socket, bind, listen), fork,
and only then call Graph_Set(). When R_open_driver() calls connect(),
that will succeed as long as the socket is actually listening, even if
the monitor is busy with Graph_Set() and doesn't actually accept() the
connection for a while (Graph_Set() can take quite a long time in some
situations).

Unfortunately, that doesn't work well with FIFOs, where you can't tell
the difference between a non-existent monitor and a monitor which is
taking its time to open its end of the FIFO.

Summary: the existing mechanism works well with X11, but can't be made
to work reliably with other window systems. The most obvious
alternative won't work well with FIFOs, but are these still important?

--
Glynn Clements <glynn.clements@virgin.net>

Glynn,

The need for the "#ifdef __W98__" was only to support the Windows 98
implementation of Cygwin. Althought the XDRIVER worked fine on Windows NT
and Windows 2000, the implementation of fork() in the cygwin library did not
work properly under Win 98. I was able to isolate the problem to the fork()
call, which in testing worked very inconsistently.

The Cygwin faq does (or did) identify issues with fork(). The solution that
I implemented (and Mike Thomas had committed to the CVS) was to spawn the
child process from mon.start rather than fork() within the XDriver (as
implemented in devices/lib/main.c).

The problems that I identified with fork() on Win98 were not consistent with
each test. Sometimes the child appeared to start, othertimes not. It
always seemed to die before the monitor was started, which may be caused by
the problem with inheriting windows resources. I suspect it is related to
Win 98's poor support for threads/process management. If I remember
correctly, the process id and parent process id were not consistently
handled during the tests, either.

The bottom line is that fork() does work OK on WinNT and Windows 2000, but
not on Win98 (unless the Cygwin implementation of fork() has been fixed).
The __W98__ fix is not needed for all cygwin users, just for Win98. Any
changes you make will have to take into account the limitations of Win98,
but don't necessarily have to be in the same for all Cygwin users.

HTH,

Malcolm

-----Original Message-----
From: wingrass-admin@grass.itc.it [mailto:wingrass-admin@grass.itc.it]On
Behalf Of Glynn Clements
Sent: Friday, January 11, 2002 4:06 PM
To: grass5@grass.itc.it; wingrass@grass.itc.it
Subject: [winGRASS] [GRASS5] display system

I've been looking into the problems with mon.start/XDRIVER which
necessitated the code which is conditionalised upon "#ifdef __W98__",
and have a few comments.

1. The problem seems to be specific to XDRIVER; the CELL driver works
fine if mon.start and src/display/devices/lib are build without
__W98__ defined.

2. The above makes sense; the Windows resources (e.g. the window)
created by Graph_Set() presumably aren't going to be inherited across
the fork() (certainly, POSIX/XPG*/Unix98 don't say anything about the
behaviour of fork() w.r.t. Windows resources).

3. This would apply equally to a "native" Windows or MacOS driver. X
is rather different because of X11's client-server architecture; the
only system resource held by an X client is the descriptor for the
connection to the X server.

4. Intuition says that __W98__ ought to be unnecessary when using the
vanilla XDRIVER under Cygwin with an X server. There have been
reported problems, although this could be a bug in Cygwin or Cygwin's
Xlib. Hard information would be welcome.

5. The existing (problematic) behaviour exists for a reason. Delaying
the "daemon-isation" (fork(), parent exit()s) until everything has
been initialised and the monitor is ready to accept connections
ensures that the monitor is ready as soon as mon.start terminates.

This ensures that the subsequent invocation of mon.select will succeed
even when mon.select is run immediately afterwards. It also explains
why, with the libW11 port, the first attempt to select the monitor
fails (and, if the initialisation were to take too long, the second
attempt would also fail).

So what, if anything, should we do about it?

One option would be to create the socket (socket, bind, listen), fork,
and only then call Graph_Set(). When R_open_driver() calls connect(),
that will succeed as long as the socket is actually listening, even if
the monitor is busy with Graph_Set() and doesn't actually accept() the
connection for a while (Graph_Set() can take quite a long time in some
situations).

Unfortunately, that doesn't work well with FIFOs, where you can't tell
the difference between a non-existent monitor and a monitor which is
taking its time to open its end of the FIFO.

Summary: the existing mechanism works well with X11, but can't be made
to work reliably with other window systems. The most obvious
alternative won't work well with FIFOs, but are these still important?

--
Glynn Clements <glynn.clements@virgin.net>
_______________________________________________
winGRASS mailing list
winGRASS@grass.itc.it
http://grass.itc.it/mailman/listinfo/wingrass

Malcolm Blue wrote:

The need for the "#ifdef __W98__" was only to support the Windows 98
implementation of Cygwin. Althought the XDRIVER worked fine on Windows NT
and Windows 2000, the implementation of fork() in the cygwin library did not
work properly under Win 98. I was able to isolate the problem to the fork()
call, which in testing worked very inconsistently.

The Cygwin faq does (or did) identify issues with fork(). The solution that
I implemented (and Mike Thomas had committed to the CVS) was to spawn the
child process from mon.start rather than fork() within the XDriver (as
implemented in devices/lib/main.c).

The problems that I identified with fork() on Win98 were not consistent with
each test. Sometimes the child appeared to start, othertimes not. It
always seemed to die before the monitor was started, which may be caused by
the problem with inheriting windows resources. I suspect it is related to
Win 98's poor support for threads/process management. If I remember
correctly, the process id and parent process id were not consistently
handled during the tests, either.

The bottom line is that fork() does work OK on WinNT and Windows 2000, but
not on Win98 (unless the Cygwin implementation of fork() has been fixed).
The __W98__ fix is not needed for all cygwin users, just for Win98. Any
changes you make will have to take into account the limitations of Win98,
but don't necessarily have to be in the same for all Cygwin users.

Are you saying that the W11 driver works on NT/2K without the __W98__?
Or does the above only apply to the "vanilla" XDRIVER (using a genuine
Xlib and X server)?

--
Glynn Clements <glynn.clements@virgin.net>

-----Original Message-----
From: grass5-admin@grass.itc.it [mailto:grass5-admin@grass.itc.it]On
Behalf Of Glynn Clements
Sent: Friday, January 11, 2002 8:39 PM
To: Malcolm Blue
Cc: wingrass@grass.itc.it; grass5@grass.itc.it
Subject: RE: [winGRASS] [GRASS5] display system

Malcolm Blue wrote:

> The need for the "#ifdef __W98__" was only to support the Windows 98
> implementation of Cygwin. Althought the XDRIVER worked fine on
Windows NT
> and Windows 2000, the implementation of fork() in the cygwin
library did not
> work properly under Win 98. I was able to isolate the problem
to the fork()
> call, which in testing worked very inconsistently.

.
.
.

Are you saying that the W11 driver works on NT/2K without the __W98__?
Or does the above only apply to the "vanilla" XDRIVER (using a genuine
Xlib and X server)?

The above applies to the vanilla XDRIVER, with an X Server. Initially, the
__W98__ was added to work around the fork() problem on Win98.

The fork() call had to be disabled for the W11 native driver for a different
reason. Since the W11 library handles all of the X functionality through
the native graphics rather than an X Server, after the Monitor window is
created in Graph_Set, the parent can't just exit or the monitor window will
be closed. The child process still ran on WinNT, but the monitor window
belonged to the parent process, so the child process was useless at that
point.

Since the __W98__ define was already in place to work around the fork()
problem for Win98, it was utilized to resolve the native window problem as
well. I was forgetting this when I said "only to support the Windows 98
implementation".

Calling Graph_Set() after the fork() should work on NT/2K, for either
"vanilla" or native XDRIVER, as you suggested since then it would be the
child process which creates the monitor window, however the __W98__ will
still be needed for Win98, unless fork() has been fixed for that
environment.

Malcolm