Blog of Raivo Laanemets

Stories about web development, freelancing and personal computers.

Catch SWI-Prolog loading errors

On

SWI-Prolog reports module loading errors onto the console but still starts up. This behavior is not wanted for web/API server processes. A module with syntax errors should not allow the process to start up in order to avoid running a misbehaving server. I had this happen to one of my applications. The application was loaded only partially and had half of its functionality not working.

This situation can be solved with some extra code. Module loading errors can be caught through the global message system. To avoid shutdown on non-loading errors, we use a global flag that is set during module loading.

:- dynamic(loading/1).
:- asserta(loading(0)).

% The first hook is for detecting
% loading state.

user:message_hook(Term, _, _):-
    (   Term = load_file(start(Level, _))
    ->  asserta(loading(Level))
    ;   (   Term = load_file(done(Level, _, _, _, _, _))
        ->  retractall(loading(Level))
        ;   true)),
    false.

% The second hook shuts down SWI when
% an error occurs during loading.

user:message_hook(Term, Type, _):-
    loading(_),
    ( Type = error ; Type = warning ),
    message_to_string(Term, String),
    writeln(user_error, String),
    halt(1).

This code must be added into the main file, before loading any modules, either through use_module or through other means. It will also catch failing and error-throwing directives. The code is a result from the discussion on the SWI-Prolog mailing list.


Comments

Markus Triska at 2016-05-22
Awesome work Raivo, as usual. Thank you for sharing this! And: Give false/0 a chance!

RLa at 2016-05-29
Thank you! I see that false/0 would be more symmetrical to true/0 than fail/0 and would read a bit more declarative. I have updated the example code. I wonder why we have no succeed/0 :)

Email is not displayed anywhere.
URLs (max 3) starting with http:// or https:// can be used. Use @Name to mention someone.