However, it seems that user_error isn’t visible for threads created in the thread pool, so I can’t see messages from debug/3.
e.g.
?- thread_create_in_pool(handler_pool, format(user_error, "hello from other thread", []), Id, []),
thread_join(Id).
% no message?
Id = <thread>(15,0x2a8553f20).
?- thread_create(format(user_error, "hello from other thread", []), Id, []),
thread_join(Id).
hello from other thread
Id = <thread>(15,0x13af49e00).
This obviously makes debugging handlers annoying. Is there a way to set the user_error stream for thread-pool-created threads?
This doesn’t reproduce (tried with my local copy of the website). I fear I need a complete example. This was a problem long ago when the pool manager was (lazily) created from a thread that had I/O connected to something unusable. As is, the pool manager should inherit its streams from the main thread and threads created in the pool inherit from the pool manager.
Ah, I see. Indeed, I see that it acts as expected when I run a normal top-level from the terminal. I suspect then this is because I’m running the top-level from sweep, inside Emacs, so the initial streams are pointing somewhere else.
Is there any way then to change the streams of the thread manager thread? I tried doing thread_exit('__thread_pool_manager'), in the hopes of restarting the manager thread with the correct streams, but that seems to have broken everything
I see. I wrote something for that when trying to get debug messages from a server in an SSH login (see the libssh pack, which allows using SWI-Prolog as ssh server such that you can safely get a remote console). Here is the code:
:- module(msg, [capture_messages/1]).
:- dynamic
captured_messages/3.
:- thread_local
thread_error_stream/1.
user:message_property(Level, stream(S)) :-
captured_messages(Level, S, _).
%! capture_messages(+Level) is det.
%
% Redirect all messages of the indicated level to the console of the
% current thread. This is part of the SSH library as it is notably
% practical when connected through SSH. Consider using trace/1 on
% some predicate. We catch capture the output using:
%
% ?- capture_messages(debug).
% ?- trace(p/1).
capture_messages(Level) :-
( thread_error_stream(S)
-> true
; thread_self(Me),
stream_property(S, alias(user_error)),
asserta(thread_error_stream(S)),
thread_at_exit(cleanup_message_capture)
),
asserta(captured_messages(Level, S, Me)).
cleanup_message_capture :-
thread_self(Me),
retractall(captured_messages(_,_,Me)).