mark@cbosgd.UUCP (Mark Horton) (11/28/83)
In 4.2BSD, if a signal interrupts a system call, the system call is resumed once the signal handler exits. While it can be argued that this behavior makes more sense, it breaks a lot of programs. Some programs have code that looks like do { printf("prompt"); caught = 0; osig = signal(SIGxxx, catch); read(0, buf, num); signal(SIGxxx, osig); } while (caught); catch(signum) { signal(SIGxxx, catch); caught = signum; } In 4.1 and all other versions of UNIX, this arranges that when SIGxxx (e.g. SIGINT or SIGCONT) comes in, the read terminates early and the prompt is printed on the next trip through the loop. in 4.2, the read resumes and only one prompt is printed, or in this case you go into a loop. I'm looking for a nice way to write clean portable code that will work with this new system and still work with the old system. ifdefs are acceptable but it would be nice to keep the number down. One way might be to use setjmp and have the signal routine longjmp to the caller, replacing the loop. Thus, you get #include <setjmp.h> jump_buf sigjmpbuf; setjmp(sigjmpbuf); caught = 0; printf("prompt"); osig = signal(SIGxxx, catch); read(0, buf, num); signal(SIGxxx, osig); catch(signum) { signal(SIGxxx, catch); longjmp(sigjmpbuf); caught = signum; } This strikes me as considerably less clear and more error-prone than the old method. Can anyone suggest a better way - perhaps a way to make 4.2 go into "4.1 mode" without modifying the kernel or C library?
dmmartindale@watcgl.UUCP (Dave Martindale) (11/29/83)
A nice clean way to handle this would be to have the signal-handling routine's return code indicate whether the system call which was interrupted, if any, should be restarted. This would still require changes to old code which doesn't return anything meaningful from the signal handler. Maybe yet another flag, specified in the call to signal that gives the handler's address?