[fa.info-vax] VAX11-C V2.0 Signals

stern@bnl.ARPA (Eric G. Stern) (08/28/85)

We recently upgraded to VAX11C V2.0, but the documentation ordered
in July has yet to be received.  However, I took a look at the
release notes and got the impression that signals should work
more like UNIX signals than they used to.  So, I bravely went
forth and wrote a program to test it, but I am getting strange
results.  Here is the program:

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>

jmp_buf	main_setjmp;

main()
{
	int i;
	int ctrlc();

	signal(SIGINT,ctrlc);
	setjmp(main_setjmp);
	for(i = 0; i < 1000; ++i) {
		printf("Value is %d\n",i);
	}
	exit(1);
}

ctrlc()
{

	printf("signal caught\n");
	fflush(stdout);
	signal(SIGINT,ctrlc);
	longjmp(main_setjmp,-1);
	return(-1);
}

The idea is that the program counts up to 1000 unless an interrupt (^C)
is received, in which case it starts all over.  I get different
behavior depending on how I am logged in.  If I log in over an
Ethernet terminal server and run the program, the first ^C I
type seems to have no effect.  The second one causes the routine
ctrlc to be activated according to the debugger, but no message
ever gets printed, and the program terminates after doing nothing
for a while.  However, if I log in over DECnet with the SET HOST
command, the first ^C prints the message and starts the count
from 0.  Any further ^C behave just like ^Y and the program
terminates, again after a second or two.  So, why does this happen?
Am I doing something wrong?

The second question I have is about a program that works, but I
don't understand why.  This program is taken from the V1.0 VAX11-C
documentation.

#define SECONDS 	5

#include <signal.h>
#include <stdio.h>

int number_of_alarms = 5;
main()
{
	int alarm_action();

	signal(SIGALRM,alarm_action);
	alarm(SECONDS);
	pause();
	return(1);
}

alarm_action()
{
	printf("alarm, alarm!!, %d alarms\n", number_of_alarms);
	if(--number_of_alarms > 0) {
		signal(SIGALRM, alarm_action);
		alarm(SECONDS);
		pause();
	}
	return;
}

This program prints out five messages spaced in five second intervals.
I don't understand why this works.  In function alarm_action, execution
is proceeding at AST level.  The pause just executes the SYS$HIBER system
service.  So, how does any other signal ever get delivered?  Won't
the process still be at AST level when the next alarm occurs?  Also,
it appears that function alarm_action is called five times, but only
returns once.  Shouldn't this mess up the stack?  Examination with
the debugger reveals that the stack pointer is the same upon each
invocation of alarm_action.  Where does the signal stack frame go each
time?

It is clear that what I am looking for is a better understanding
of signal implementation in the context of the VMS system.  Does
the new VAX11-C documentation provide an explanation?  From what
I have been able to discover, a signal proceeds with an AST call
to a library routine, which uses the LIB$SIGNAL call to transfer
into the VAX11-C condition handler which then does something?  But
what?

				Eric G. Stern
				Dept. of Physics
				SUNY StonyBrook
				StonyBrook, NY 11794
				(516) 282-3773
				stern@bnl.arpa
				stern@bnl.bitnet
				...!philabs!sbcs!bnl!stern

KVC%cit-vax@engvax.UUCP (08/30/85)

Yeah, I'm having a problem with signals and longjmp as well.  In my case,
the following simple program doesn't work:
----------------------------------------------------------------------------
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
jmp_buf buf;
alarmtr()
{
	longjmp(buf, 1);
}
main()
{
	if (setjmp(buf)) {
		puts("This line should print every 5 secs forever!");
	}
	signal(SIGALRM, alarmtr);
	alarm(5);
	pause();
}
----------------------------------------------------------------------------

This program seems to have two problems.  First of all, the signal
only gets handled once (like in C V1).

The program also exhibits some weird behaviour in the pause() call -- it
actually manages to exit, which should be impossible.  Somehow, the
alarm manages to queue 2 wakeup requests, so the second time it goes
into pause(), there is an extra wakeup request hanging around and the
program wakes up without going to alarmtr and exits to DCL!  I have
SPR'ed this, but haven't gotten an answer yet (and it's been many weeks).

With an infinite loop instead of a pause, it only gets one signal.

In C V1, it was documented that longjmp and signals didn't work right,
since you were left at AST level and future signals got ignored.  This
is supposedly fixed in V2, but it doesn't seem to be.  For whatever reason,
future signals are still ignored after a longjmp out of a signal handler.
In V1 I had a work around with a neat little piece of macro that faked
an AST dismissal without exiting the AST routine, but that doesn't work in
C V2.  So, I am stuck with a big piece of code I cannot recompile.  Yuck.

	/Kevin Carosso        engvax!kvc @ CIT-VAX.ARPA
	 Hughes Aircraft Co.