[comp.windows.x] SysV, signals and X

dmh@goanna.oz (Darren Hosking) (09/20/89)

Due to the nature of System V signal handling it is possible for system
calls within an X library (specifically Xlib) to be interrupted, ie the
system call that was interrupted will return an error (-1) and errno will
be set to EINTR.

This is not a problem in _XRead(), which does a read() from the socket to
the server, as the interrupted system call error is explicitly checked for
and the XIOErrorFunction is NOT called if the read() was interrupted.

However, in _XSend, which does a write() to the socket connected to the
server, the interrupted system call error is not checked for and therefore
the XIOErrorFunction will be called if the write() is interrupted.

How can you use signal() and your own signal handlers without the client
generating an error message and exiting (because of the interrupted syscall)?

For example, if you want to run an infinite loop of X calls (drawing
rectangles or whatever) which is stopped by a SIGALRM and a signal handler,
how can you guarantee that system calls within Xlib (or other X libraries)
will not be interrupted and abort?

One solution is to ignore the given signal each time you want to call an
Xlib function and then reinstate it after the call, but the system call
overhead could be substantial.

Any ideas or solutions?

	Thanks in advance, dmh

Darren Hosking				ACSnet: dmh@goanna.oz	 
Department Of Computer Science		ARPA:   dmh%goanna.oz.au@uunet.uu.net
RMIT					CSNET:  dmh%goanna.oz.au@australia
GPO Box 2476V				UUCP:   ...!uunet!goanna.oz.au!dmh
Melbourne Vic., Australia 3001

keith@EXPO.LCS.MIT.EDU (Keith Packard) (09/21/89)

> However, in _XSend, which does a write() to the socket connected to the
> server, the interrupted system call error is not checked for and therefore
> the XIOErrorFunction will be called if the write() is interrupted.
> 
> How can you use signal() and your own signal handlers without the client
> generating an error message and exiting (because of the interrupted syscall)?

The problem with SysV is worse than you imagine.  Write(2) blocks when the
receiver buffer fills up.  At this point, the signal may be processed, and the
write(2) may return EINTR.  But, the client has no way of discovering how many
bytes were written to the socket *before* the write was blocked and then
interrupted.  If some data were sent to the server, the connection will become
hopelessly out-of-sync.  This is why the XIOErrorFunction is called when
write(2) return EINTR; the client cannot continue using the current display
connection.  Read(2) doesn't have this trouble as it returns either whatever
data is currently availible (without blocking) or waits for some data to
arrive.  When read(2) returns EINTR, no data could have been read yet.

The only solution on native SysV is to use something other than signals.

Keith Packard
MIT X Consortium

davidp@labtam.oz (David Purdue) (09/21/89)

From article <2400@goanna.oz>, by dmh@goanna.oz (Darren Hosking):
> Due to the nature of System V signal handling it is possible for system
> calls within an X library (specifically Xlib) to be interrupted, ie the
> system call that was interrupted will return an error (-1) and errno will
> be set to EINTR.
> 
> How can you use signal() and your own signal handlers without the client
> generating an error message and exiting (because of the interrupted syscall)?
> 
> For example, if you want to run an infinite loop of X calls (drawing
> rectangles or whatever) which is stopped by a SIGALRM and a signal handler,
> how can you guarantee that system calls within Xlib (or other X libraries)
> will not be interrupted and abort?

I just came across this problem while trying to do a benchmark
with xbench. The situation is exactly as in the example above.

What I do is this: I set up the signal handling routine using
setsig(2), then around the call to Xlib in the relevant loop
I put sighold(2) and sigrelse(2). Thus signal handling is turned
off while X does its stuff.

I have found that the system call overhead for doing this is
not prohibitive, and it does not affect the xbench results
because xbench always completes its operation before checking
if the alarm went off anyway.

						DavidP
====
Mr. David Purdue        Phone ISD: +61 3 587 1444  Fax: +61 3 580 5581
Labtam Information          Telex: LABTAM AA33550
  Systems Pty Ltd,
43 Malcolm Road,     ACSnet/CSnet: davidp@labtam.oz
BRAESIDE,                    ARPA: davidp%labtam.oz@uunet.uu.net
VICTORIA, 3195.             JANET: davidp@oz.labtam
AUSTRALIA                    UUCP: ...!uunet!munnari!labtam.oz!davidp

"Maybe I think too much." - Paul Simon

randy@erik.UUCP (Randy Brown) (09/21/89)

expo.lcs.mit.edu!keith (Keith Packard) writes:
> The problem with SysV is worse than you imagine.  Write(2) blocks when the
> receiver buffer fills up.  At this point, the signal may be processed, and the
> write(2) may return EINTR.  But, the client has no way of discovering how many
> bytes were written to the socket *before* the write was blocked and then
> interrupted.

My copy of the draft for comment of FIPS151-1, changes to IEEE 1003.1
POSIX, says in part:

In Section 6.4.2.2, the sentence "If a write() is interrupted by a signal
after it successfully writes some data, either it shall return -1 with
errno set to [EINTR] or it shall return the number of bytes written."
shall be deleted and replaced with the sentence "If a write() is
interrupted by a signal after it successfully writes some data, it shall
return the number of bytes the system has written."

So, as most major vendors like to sell to the feds, there's hope. Just
start now making clear that you want the FIPS POSIX version and not the
commercial POSIX version, which has a few more options to exercise that
can introduce incompatibility. For example, FIPS POSIX must support job
control (at the system call level), but IEEE POSIX has it optional.

Of course, this doesn't necessarily solve this week's problems. ... rb