[comp.lang.prolog] Interrupt Handler for Quintus Prolog

waldmann@exunido.uucp (Uwe Waldmann) (03/07/90)

I am trying to write an interrupt handler for Quintus Prolog (Rel. 2.4.2 on
a Sun-3 and/or a Sun-4).  I wanted to take the demo example from the
"Quintus Prolog System-dependent Features Manual" (p. 15) as a starting
point, but unfortunately even this (unmodified) example does not work
properly:

/* ------ interrupt.c from "QP System-dependent Features Manual" ------ */

#include <signal.h>
#include "/usr/local/q2.4.2/library/qpaction.h"

int my_handler()
{
    char c;

    for (;;) {
        printf("\nWell? ");
        c = getchar();
        if (c != '\n')
            while (getchar() != '\n') {};
        switch (c) {
            case 'a': QP_action(QP_ABORT);  /* abort */
            case 'e': QP_action(QP_EXIT);   /* exit */
            case 'c': return;               /* continue */
            default: printf("a, c or e, please");
        }
    }
}

void establish_handler()
{
    signal(SIGINT, my_handler);
}

% ------- interrupt.pl from "QP System-dependent Features Manual" --------

foreign_file('interrupt.o', [establish_handler]).
foreign(establish_handler, establish_handler).
:- load_foreign_files(['interrupt.o'], []).
:- establish_handler.

% ------- test -----------------------------------------------------------

uwe@issan(1)% cc -c interrupt.c
uwe@issan(2)% qprolog

Quintus Prolog Release 2.4.2 (Sun-4, SunOS 4.0)
Copyright (C) 1988, Quintus Computer Systems, Inc.  All rights reserved.
1310 Villa Street, Mountain View, California  (415) 965-7700

| ?- compile(interrupt).
[compiling /home/helga/uwe/testdir/qp-interrupts/interrupt.pl...]
 [foreign file /home/helga/uwe/testdir/qp-interrupts/interrupt.o loaded]
[interrupt.pl compiled 0.100 sec 21,312 bytes]

yes
| ?- ^C                         % type interrupt character ^C
Well? a                         % new interrupt handler is invoked
[ Execution aborted ]           % okay, abort command is handled properly


| ?- ^C                         % type interrupt character ^C again
Well? c                         % now try the "continue" command
                                % type <return>: nothing happens
                                % once more <return>: still no prompt
     true.                      % now type in a goal

** Syntax error:  **
m                               % where does this "m" come from???
** here **
true

% ------- end of test ----------------------------------------------------

If I repeat the last part, I get a "u" insted of an "m".  It looks, as if
the input buffer gets corrupted somehow.  On a Sun-3 and a Sun-4 the results
are the same.

Has somebody already noted this strange behaviour?  Is there a bug in
"interrupt.c"?  (Well, I know that declaring "my_handler" as "int" is bad
style, but with "void" I get the same result.  I have also tried to put a
"return" after the "a" and "e" cases, but this didn't fix it either.)
Or is it a bug in Quintus Prolog?  Is there any workaround known?

--
Uwe Waldmann
LS Informatik V
Universitaet Dortmund
Postfach 50 05 00
4600 Dortmund 50
West Germany

e-mail: uwe@ls5.informatik.uni-dortmund.de

don@quintus.UUCP (Don Ferguson) (03/09/90)

In article <2030@laura.UUCP> waldmann@exunido.UUCP (Uwe Waldmann) writes:
>I am trying to write an interrupt handler for Quintus Prolog (Rel. 2.4.2 on
>a Sun-3 and/or a Sun-4).  I wanted to take the demo example from the
>"Quintus Prolog System-dependent Features Manual" (p. 15) as a starting
>point, but unfortunately even this (unmodified) example does not work
>properly:

The problem you report refects a SunOS bug.  Apparently getc() is no longer
re-entrant.  If getc() is interrupted and the interrupt handler calls getc(),
then, on return, the original getc() will yield bad values - it's internal
buffer has become corrupted.  I proved this to myself by modifying the example
to contain only C code.  The code ran correctly under SunOS 2.3, but not under
SunOS 3.2 or 4.0.3.

Avoid the problem by calling read() from the interrupt handler instead of
getchar. (NOTE: getchar is just a macro that calls getc(stdin)).

#include <signal.h>
#include <stdio.h>
#include "/goedel/quintus/install/q2.4.2/library/qpaction.h"

int my_handler()
{
    char c, c1;

    for (;;) {
        printf("\nWell? ");
	fflush(stdin);
	read(0, &c, 1);
	c1 = c;
	while (c1 != '\n') {
		read(0, &c1, 1);
	}
	fflush(stdin);
        switch (c) {
            case 'a': QP_action(QP_ABORT);  /* abort */
            case 'e': QP_action(QP_EXIT);   /* exit */
            case 'c': return;               /* continue */
            default: printf("a, c or e, please");
        }
    }
}

Thanks for pointing out this discrepancy in our manual.  We will update
our documenatation accordingly.


    -Don Ferguson
     Manager, Technical Services