Embedding without signals

I’m trying to embed SWI prolog without it taking over signal handlers, and having a bit of trouble.

char *swipl_argv[2] = {argv[0], "--no-signals"};
PL_initialise(2, swipl_argv);

seems to still set up at least a SIGINT handler, as verified by on_signal/3.

Passing -pl-options,--no-signals to swipl-ld doesn’t help either.

Which version? A small test:

swipl --no-signals
<banner>

1 ?- on_signal(int, O,O).
O = default.

2 ?- current_prolog_flag(os_argv, X).
X = [swipl, '--no-signals'].

And ^C indeed does nothing.

$ swipl --no-signals
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.2)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- on_signal(int, O, O).
O = default.

?- current_prolog_flag(os_argv, X).
X = [swipl, '--no-signals'].

I reproduce that; it’s only in binaries in which I’m embedding the Prolog engine that I’m finding it difficult to disable signals.

edit: and in that case, printing all solutions to a(X), where

a(signal(X)) :- on_signal(int, X, X).
a(os_argv(X)) :- current_prolog_flag(os_argv, X).

I get

signal(debug)
os_argv(['./out/whgvah','--no-signals'])

Strange. I’d first try to get os_argv and validate that. Note that you do need to make sure that the argument vector you pass to PL_initialize() remains valid during the execution of Prolog. If this doesn’t help, please supply short complete code we can compile and run.

Reproducer:

$ cat main.c
#include <SWI-Prolog.h>
#include <stdio.h>
#include <unistd.h>

static void display(term_t);

int main(int argc, char **argv) {
  char *swipl_argv[2] = {argv[0], "--no-signals"};
  if (!PL_initialise(2, swipl_argv)) {
    fprintf(stderr, "Failed to initialize Prolog!\n");
    PL_halt(1);
  }

  predicate_t a = PL_predicate("a", 1, NULL);
  term_t out = PL_new_term_refs(1);
  qid_t query = PL_open_query(NULL, PL_Q_NORMAL, a, out);

  while (PL_next_solution(query)) {
    display(out);
    printf("\n");
    sleep(1);
  }

  if (!PL_close_query(query)) {
    fprintf(stderr, "Exception while closing query!\n");
    PL_halt(1);
  }

  return 3;
}

static void display(term_t term) {
  char *str;
  PL_STRINGS_MARK();
  if (!PL_get_chars(term, &str, CVT_WRITE_CANONICAL | BUF_STACK | REP_UTF8)) {
    fprintf(stderr, "Cannot convert term to string!\n");
    PL_halt(1);
  }
  printf("%s", str);
  PL_STRINGS_RELEASE();
}

$ cat main.pl
nat(z).
nat(s(N)) :- nat(N).

a(signal(X)) :- on_signal(int, X, X).
a(os_argv(X)) :- current_prolog_flag(os_argv, X).
a([N|N]) :- nat(N).

% set vim: ft=prolog :

$ swipl-ld -g -goal true -pl-options,--no-signals -Wall -Werror -o main main.c main.pl
% Disabled autoloading (loaded 30 files)
% Disabled autoloading (loaded 2 files)
% Disabled autoloading (loaded 0 files)
% halt

$ ./main
signal(debug)
os_argv(['./main','--no-signals'])
[z|z]
[s(z)|s(z)]
[s(s(z))|s(s(z))]
[s(s(s(z)))|s(s(s(z)))]
[s(s(s(s(z))))|s(s(s(s(z))))]
[s(s(s(s(s(z)))))|s(s(s(s(s(z)))))]
[s(s(s(s(s(s(z))))))|s(s(s(s(s(s(z))))))]
^CAction (h for help) ? abort

This reproduces. I pushed some changes to make the --no-signals propagate through creating a saved state. Besides updating to the git version your best option is probably to use on_signal/3 to disable handling the signals you do not want Prolog to catch.

1 Like