Blog of Raivo Laanemets

Software development and personal stories.

Catch SWI-Prolog loading errors

On 2016-05-21

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.