Process_create doesn't work inside http_handler

I’m using: SWI-Prolog version 8.0.3 (though I also tried updating to 8.1.21 and had the same problem).

I’m trying to modify my website to allow users to call a particular program I’m working on. When I use process_create/3 in Prolog “normally”, i.e., from the REPL, then everything works fine. However, when I try to call it from inside the HTTP handler, everything returns some nonzero exit code (ls gives me 2, pwd and echo give me 1, etc.). Below is a complete, simple program that demonstrates this:

:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_unix_daemon)).

:- use_module(library(process)).

:- initialization(start_server, main).

:- http_handler(root('run'), try_run, []).

start_server :-
    try_run(_),
    http_daemon([port(8080), user(root)]).

try_run(_Request) :-
    format('Content-type: text/plain~n~n', []),
    setup_call_cleanup(
        process_create(path(echo), ['hello world'], [process(PID)]),
        true,
        process_wait(PID, Code)),
    format('exited with: ~w~n', [Code]).

Obviously running as root isn’t ideal, but I wanted to be sure there were no permission errors or anything.

Above, we can see that if we just run start the server, the call to try_run/1 works inside start_server/0.

roei@roei-main:~$ swipl --version
SWI-Prolog version 8.0.3 for x86_64-linux
roei@roei-main:~/Prolog/website$ sudo swipl t.pl
Content-type: text/plain

hello world
exited with: exit(0)

But if I try to make a request:

roei@roei-main:~/Prolog/website$ curl -X POST localhost:8080/run
exited with: exit(1)

I’m running Ubuntu 18.04.

I also posted this to Stack Overflow (https://stackoverflow.com/questions/60031665/prolog-process-create-doesnt-work-inside-http-handler?noredirect=1#comment106168273_60031665), but I was directed here as a possible place to get help.

1 Like

Welcome, I was the one who gave you the comment on StackOverflow.

While I can not answer the question, this is where I would ask. :slightly_smiling_face:

It seems that the problem is that whatever process_create/3 uses as the default output stream is not able to be written to, for whatever reason. But if I change it to:

try_run(_Request) :-
    format('Content-type: text/plain~n~n', []),
    setup_call_cleanup(
        process_create(path(echo), ['hello world'], [process(PID), stdout(pipe(Stream))]),
        true,
        process_wait(PID, Code)),
    current_output(Out),
    copy_stream_data(Stream, Out),
    format('exited with: ~w~n', [Code]).

i.e., manually setting up the output stream, it works now.

The output of the created process should point at the normal process output (stdout, user_output in Prolog). You anyway need to handle the output as (I guess) you want it to end up in the web page?

Note though that what you are doing now does not work. If the process produces a lot of output it will block because nobody is reading before the process is finished. You can find a lot of examples on handling process output in library(git).

You also might want to have a look at https://github.com/SWI-Prolog/plweb/blob/ad4fdd235510295d57e3178f2e6a83462147a5e5/http_cgi.pl
Not sure this still works as it isn’t in use for the Prolog web server for a long time.