signal handling in 4.2

Mark Horton mark at cbosgd.UUCP
Mon Nov 28 10:13:02 AEST 1983


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?



More information about the Comp.unix.wizards mailing list