cak@Purdue.ARPA (01/12/84)
From: Christopher A Kent <cak@Purdue.ARPA> I think it's wonderful from a purely pragmatic standpoint. I probably won't write any new code that uses it (I'm a true believer), but we have so much old code that uses it that things have been a real pain around here trying to convert it all and leave it portable (one program system in particular, which we distribute, needs to be able to run on 4.1 and 4.2 and has to do timeouts of reads). By leaving the default behaviour as restartable system calls, "new" programmers will be encouraged to use that model, especially if they have only read as much as they need to know and haven't seen the manual page for sigrestartable yet. I think it's a win all around. Cheers, chris ----------
mike%rice@sri-unix.UUCP (01/12/84)
From: Mike Caplinger <mike@rice> [This message has a possibly worthwhile suggestion at the bottom. Readers interested in skipping the rest can feel free to do so. - Mike Caplinger] First, as I understand them 4.2 restarting is exactly like 4.1 restarting after a new signal feature has been used. This is already a compatibility problem. Most 4.1 programs I've written have used the new interface. I'm really scared of making any changes to 4.2 that don't make it into ALL the distribution tapes that are going to be sent out. I like Mike's solution, but do you really think it's worthwhile trying to do such things in the name of portability? I believe the following things: 1) There will be many 4.2 programs that will never run under Sys V. 2) There will be many Sys V programs that will never run under 4.2. 3) Most educational sites will never run Sys V on VAXen. We would only run Sys V on any machine if we were stuck with it. Experience with the millions of local hacks that ran around under v7, and trying to cope with /usr/group and Usenix software that used them, has made me very wary of local hacks. I suspect there will always be purists who refuse to implement local hacks; I even think I'm one of them. I wonder if, now that rumors say Berkeley isn't really doing development work, we might get people there to listen to improvements like yours. How about Ultrix? Will DEC listen? Also, it has always bothered me that the terminal driver in 4.1 made it necessary to do as many as 4 ioctls in order to do logically-connected things. That was a compatibility move too... Of course, this change doesn't using the new semantics clumsy. I guess what I would like is for the change to be added, but controlled by the COMPAT #ifdef. Good luck lobbying for it! - Mike ps. If signal() was kept as a COMPAT system call, and a front-end was written to go in a special library (liboldsig?) then use of that system call (as opposed to the signal(3) library call) could detect whether new or old behavior was wanted, obviating the sigrestartable syscall, just as 4.1 detected the use of a new feature and set SOUSIG accordingly. I think...
gwyn%brl-vld@sri-unix.UUCP (01/12/84)
From: Doug Gwyn (VLD/VMB) <gwyn@brl-vld> I think perhaps you are attempting to bundle too many things together that should be orthogonally selectable. I would much prefer that the state of the u_eosys flag bit RESTARTSYS be available to the signal handler and that there be a way to turn off this bit before resuming after the signal handler. As with your proposal, any program not using this added feature would obtain the distributed 4.2BSD behavior. This addition would permit the machine dependencies to be removed from the signal(2) emulation that I previously posted, so that "old style" UNIX signal behavior would be available simply by using the signal() library routine, with no extra BSD-specific kludge calls needed in user source code.
guy@rlgvax.UUCP (Guy Harris) (01/14/84)
First, as I understand them 4.2 restarting is exactly like 4.1
restarting after a new signal feature has been used. This is
already a compatibility problem. Most 4.1 programs I've written
have used the new interface.
I believe this is correct; the "vnews" we ran on 4.1 used the new signal
mechanism so that it could be suspended, and it turned out that typing
one's interrupt character didn't work like it was supposed to because the
read didn't get EINTR, so I had to stick in a (surprise, surprise) "setjmp"/
"longjmp" pair.
Also, it has always bothered me that the terminal driver in 4.1 made it
necessary to do as many as 4 ioctls in order to do logically-connected
things. That was a compatibility move too... Of course, this change
doesn't using the new semantics clumsy.
This was actually somewhat inherited from V7; the System III/System V handler
cleans this up, although if 4.3BSD or whatever picked up the USG tty driver
and then re-Berkeleyized it they might have to introduce a second "ioctl" to
turn on the local flags and supply the local control characters, which would
bring us back to where we started from...
ps. If signal() was kept as a COMPAT system call, and a front-end was
written to go in a special library (liboldsig?) then use of that system
call (as opposed to the signal(3) library call) could detect whether new
or old behavior was wanted, obviating the sigrestartable syscall, just
as 4.1 detected the use of a new feature and set SOUSIG accordingly.
I think...
"signal()" is already kept around in 4.2 as part of the 4.1 binary compatibility
feature, and if you issue the "old signal" system call it does, indeed, set
SOUSIG (in fact, that's the *only* place SOUSIG gets set), so your suggestion
has already been implemented in vanilla 4.2BSD if you define COMPAT when you
build your system.
Guy Harris
{seismo,ihnp4,allegra}!rlgvax!guytjt@kobold.UUCP (01/15/84)
Actually, this is a follow-on to:
Also, it has always bothered me that the terminal driver in 4.1 made it
necessary to do as many as 4 ioctls in order to do logically-connected
things. That was a compatibility move too... Of course, this change
doesn't using the new semantics clumsy.
This was actually somewhat inherited from V7; the System III/System V handler
cleans this up, although if 4.3BSD or whatever picked up the USG tty driver
and then re-Berkeleyized it they might have to introduce a second "ioctl" to
turn on the local flags and supply the local control characters, which would
bring us back to where we started from...
If you "re-Berkeleyize" the USG tty driver, any additional ioctl should
work in the spirit of the USG ioctl's, and let you set *all* the flag
words/special characters with a single ioctl. I thought part of the
reason for all them ioctl's in the 4BSD tty driver (actually from
IIASA) was leftover from V6 days when the stty/gtty entry point was
passed *exactly* three int's (or six char's) from user space, and this
was carried over as a superstition.
--
Tom Teixeira, Massachusetts Computer Corporation. Westford MA
...!{ihnp4,harpo,decvax}!masscomp!tjt (617) 692-6200 x275mike%brl-vgr@sri-unix.UUCP (01/18/84)
From: Mike Muuss <mike@brl-vgr>
REFRESHER.
On 4.1 and earlier UNIX systems, signal handlers had several attributes:
*) After a signal was caught, the handler was reset to SIG_DFL.
*) If the process was executing a (kernel) sleep() at "low" priority,
and a signal was processed, the system call would abort, returning
an error code (-1), with errno = u.u_error = EINTR (interupted
system call).
On 4.2 BSD UNIX, these two aspects of signal handling were altered
(along with some other, nice improvements, which are not germane).
1) The signal handler remains "installed" until explicitly changed.
2) System calls which may (kernel) sleep() at "low" priority will
be silently restarted after processing an incomming signal.
The signal handler will have no idea if this is happening or not.
PROBLEM.
Clearly, programs written for the old style signal interface will have
a fair amount of difficulty coping with difference #2 above, if they
depend on signals (especially timer signals) interrupting a system
call. Network software which wishes to run timouts around network
reads will have to longjmp() in the signal handler, rather than
being able to depend on just returning, with an EINTR to be returned
from the read/write sys-call that timed out. Editors and shells
will have to expect their I/O to be restarted after SIGINT, etc.
(You would not believe the crud that Berkeley had to do to /bin/sh
to make it still capable of re-printing $PS1 after a SIGINT (^C, etc).).
Certainly, change #1 is "mostly harmless"; the number of programs
which will break is minimal -- the timing windows which this change
fixes were something that no mortal programmer would dare depend on.
However, change #2 is truely problematic: Certainly, there are advantages
to the new style signal interface, and programs which are written with
this style of operation in mind should work out well. However, no matter
how hard we try, few of us will be able to afford the luxury of running
4.2 BSD on *all* our machines. Those of you planning on purchasing
a Cray-2 (as we are), will have to contend with System-V UNIX (at least
to start with). Many other vendors will be non-4.2 BSD, and it is too
late to stomp them all out (pitty, no?). And somehow, those venerable
old PDP-11s just keep on refusing to quit!
THEREFORE, the problem of program portability rears it's ugly head.
4.2 people (true believers) will, of course, deisre to import quality
software from elsewhere ("expensive, yes, extravagant, no"), without
having to re-write all the signal code. Others may wish to be able
to use 4.2 code on their own system ("rotsa-ruck"). Being in the
former camp, I would like to offer the following solution:
PROPOSED SOLUTION.
In proc.h, SOUSIG (1 bit in p_flag) is defined to mean "this process is using
the old signal mechanism". This piece of information is used in two ways:
1) To determine resetting of default signal handling after traps
(in sys/kern_sig.c and sys/kern_xxx.c).
2) To determine restartability of interrupted ("slow") system calls
(in kern_exit.c, sys_generic.c, sys_inode.c).
By adding another bit to the p_flag word called SDFLSIG and assigning
it function #1 (above) to this new bit, and then redefining the meaning
of SOUSIG to JUST function #2 (above), +and+ by adding a new sys-call
(#151, sigrestartable()) which permits the user to manipulate the
state of the SOUSIG bit, then a solution can be achieved.
For programs which do not use the new sys-call, standard 4.2 functionality
occurs.
Programs which wish to avoid having their sys-calls restarted may say:
sigrestartable( 0 );
and get the 4.2 interface, with continuously installed signal handlers,
but with sys-calls returning the old familiar EINTR.
Calling sigrestartable() with a non-zero argument restores the 4.2 BSD
style restartable sys-calls, so that one can "live in both worlds"
by switching back and forth. The sys-call is as fast as getpid(),
so pairs could reasonably be used around old-fashioned code if one
desires to "blend" signaling style within a single program.
STATUS.
This evening, I installed the change I proposed above, into 2 of our 780s.
Effort to change:
h/proc.h 2 lines
sys/init_sysent.c: 1 line
sys/syscalls.c: 1 line
sys/kern_sig.c 14 lines
sys/kern_exec.c 1 line
sys/kern_fork.c 1 line
sys/kern_xxx.c 1 line
To the best of my ability to test it, this new system call operates
exactly as I have described above.
QUESTION.
What does the UNIX-community-at-large think of this strategy?
If people feel that this is a reasonable solution to the 4.2 signal
"problem", DPK and I will arrange to reproduce many copies of a
1-page document describing how to install this code into your 4.2
kernel, and distribute them at UNIFORvM in Washington DC next week.
On the other hand, if a better proposal can be brought forth,
I am willing to withdraw this proposal and implement something
else, assuming that it offers a solution of similar generality,
elegance, and simplicity (pardon the self-admiration).
CREDIT.
The motivation for addressing this problem at this time came from
a program which Doug Kingston has been working on. His struggles,
his requests, and his constructive feedback were instrumental in
shaping the form of this solution. Together we evaluated 7 or 8
different solutions to this problem, before the present solution
was arrived at.
COMMENTS.
Please mail your responses to this issue back to the full list.
This issue is too important to discuss privately.
Best,
-Mike Muuss
SOURCE CODE.
Just in case you desire to try this change yourself, here is the code:
h/proc.h (2 changes):
change comment to:
#define SOUSIG 0x0100000 /* old signal semantics: no restart (BRL) */
add at the bottom:
#define SDFLSIG 0x2000000 /* reset signals to default handling (BRL) */
sys/init_sysent.c (2 lines from the bottom):
1, sigrestartable, /* 151 = sigrestartable (BRL) */
sys/syscalls.c (1 line from the bottom):
"sigrestartable", /* 151 = sigrestartable */
sys/kern_xxx.c (3 lines from the bottom):
from:
p->p_flag |= SOUSIG;
to:
p->p_flag |= SOUSIG|SDFLSIG;
sys/kern_exec.c (80% into the file):
from:
u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SOUSIG);
to:
u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SOUSIG|SDFLSIG);
sys/kern_fork.c (50% into the file):
from:
rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG));
to:
rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SOUSIG|SDFLSIG));
sys/kern_sig.c (in psig(), 85% into the file):
from:
if (p->p_flag & SOUSIG) {
to:
if (p->p_flag & SDFLSIG) {
and, after
#define cantmask (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP))
near the front of the file, add this routine:
sigrestartable() /* BRL-specific */
{
register struct a {
int restartable;
} *uap = (struct a *)u.u_ap;
/* BRL syscall to permit non-restartable signal behavior */
if( uap->restartable )
u.u_procp->p_flag &= ~SOUSIG; /* Restartable */
else
u.u_procp->p_flag |= SOUSIG; /* Non-restartable */
}
HAPPY HACKING!guy@rlgvax.UUCP (Guy Harris) (01/22/84)
> If you "re-Berkeleyize" the USG tty driver, any additional ioctl should > work in the spirit of the USG ioctl's, and let you set *all* the flag > words/special characters with a single ioctl. I thought part of the > reason for all them ioctl's in the 4BSD tty driver (actually from > IIASA) was leftover from V6 days when the stty/gtty entry point was > passed *exactly* three int's (or six char's) from user space, and this > was carried over as a superstition. The multiple "ioctl"s to set the terminal modes in 4BSD comes from V7, where they also had multiple "ioctl"s. I suspect the reason was that the V7 driver was done, it was done by adding stuff to the V6 driver which did have to use only what the "stty/gtty" routines could handle, so instead of redoing the "ioctl" interface entirely they added new "ioctl"s, and Berkeley continued the tradition for compatibility (i.e., "stty/gtty" and the old "ioctl"s still worked). The people who did the 3.0 driver probably decided that, instead of taking the V6-like 2.0 driver and adding all the V7 "ioctl"s, they'd redo the whole thing right. In 4.1cBSD there was sort of a half-assed attempt at redoing the "ioctl"s - they added an "ioctl" to set the "sg_flags" and local flags words as one "long", and an "ioctl" to set all the special characters, but one still had to use the old "ioctl" to get/set the speeds - but that was backed out in 4.2BSD. My only concerns about extending TCGETA/TCSETA to include more special characters and flag bits would be: 1) Adding the flag bits to existing words might conflict with future extensions from Bell; adding a new word would be safe but slightly ugly (for instance, the "echo control characters as ^x" bit belongs in c_lflag but Bell may eventually use all 16 bits of that "short"). 2) Programs which do a TCSETA without first doing a TCGETA on the standard input/output/error deserve to break (the *only* right way to set the modes on a port whose modes have already been initialized is to read the current modes, change the "termio" structure, and set the modes), but some programs which do the first open on a line and set the modes directly (communication programs, for instance) might break because they set the new mode bits and control characters to zero without realizing that this may have an undesired effect. By and large, setting the bits to zero would be harmless, as leaving those bits off leaves the driver behaving like the standard USG tty driver, but setting the control characters to zero doesn't disable them. The latter is actually a misfeature of the driver to some degree; for example, "getty" under System III sets your "break" or "eol" character (V7 calls it the "break" character and USG UNIX calls it the "eol" character) to NUL (zero) rather than '\377'. The latter was guaranteed to disable the control character in V7, as the character was masked down to 7 bits before it was compared against the special characters, but may not do so in USG UNIX as the stripping of the eighth bit is an option which can be set independently of most other options (this is useful, for instance, if you have a terminal with a META key which turns the eighth bit on; you can use the META key without all the disadvantages, like disabling XON/XOFF, of the V7 "raw" mode). The UNIX 2.0 backward compatibility "ioctl" TIOCSETP (which several people may have made backward compatible with V7 instead) sets the EOL (and the S5 EOL2) characters to 0, also. I would vote for changing the USG driver to consider NUL not to ever be the erase, kill, interrupt, quit, EOF, EOL, EOL2, etc. character, so that setting that character in the "termio" structure to NUL would be the official way to disable them. This would mean that most (if not all) programs which initialized a terminal port would not enable those characters if what the program did was fill in a structure and do a TCSETA without first doing a TCGETA. Under these circumstances, changing the shape of "struct termio" would only break binary images of programs, and if that was really a problem TCSETA, etc. could be given different "ioctl" numbers and the old ones could be left around for backwards compatibility. Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy