1

I'm trying to make a simple timed menu in SWI-Prolog. The user should be able to hit a key to select an option, or if they press nothing it will automatically select the default option after a few seconds. I wrote this to test the character input:

char_time:- catch(call_with_time_limit(5, get_single_char(X)), time_limit_exceeded, writeln('Too late!')),
            (ground(X) -> (char_code(Y, X), write('You picked '), writeln(Y)); true).

When I call ?- char_time. and enter a character, it behaves as expected. If I don't enter a character, it prints "Too late!" and returns true as it should, but then I get the error message:

ERROR: '$raw_read'/2: I/O error in read on stream user_input (Interrupted system call)
ERROR: I/O error in read on stream user_input (Interrupted system call)
ERROR: In:
ERROR:    [7] throw(error(io_error(read,user_input),context(...,'Interrupted system call')))

Is there any way around this problem? I thought of replacing get_single_char/1 with something else, but most other predicates similar to it wait for you to press Enter, and I'd prefer the menu to be operated with a single key press.

Jamie
  • 21
  • 4
  • The I/O library read evidently throws an exception when interrupted. Try wrapping `char_time` in a catch that checks for the I/O error. – lurker Apr 02 '18 at 00:21
  • I tried `?- catch(char_time, _, true)` but I still got the same error. It seems as if interrupting `get_single_char(X)` may cause an error at the operating system level, which the interpreter "passes on" but can't prevent. I was running Ubuntu 14.04.5 LTS if that helps – Jamie Apr 02 '18 at 02:02
  • 1
    I tried with the last released version, and verified the very same anomaly nesting catch. Then I suggest to post on SWI mailing list, where presumably you'll get some serious answer – CapelliC Apr 02 '18 at 16:41

1 Answers1

0

You could use a select with timeout instead of calling a blocking read and then interrupt it via external timeout. The problem is that many stream libraries are not safe concerning interrupts,

you might loose data in the inbetween buffering whatever, I noticed this already in other languages, like java.io. The SWI-Prolog predicate for this select is wait_for_input/3, see here:

Wait for input on one of the streams in ListOfStreams and return a
list of streams on which input is available in ReadyList.
wait_for_input(+ListOfStreams, -ReadyList, +TimeOut)
http://www.swi-prolog.org/pldoc/man?predicate=wait_for_input/3

Disclaimer: I don't know whether it really works for console input.