Problem with pengine_self?

I am using SWI-Prolog 8.0.2 on Ubuntu Linux 18.04.

I wrote the following predicate to redirect write calls to pengine_output:

% This predicate calls pengine_output if we are in a Pengines context, otherwise
%   write() is called.
x_write(Str) :-
    % This call will fail if we are NOT running in a Pengines context.
    pengine_self(Pid),
    !,
    % We are running in a Pengines instance, use pengine_out.
    pengine_output(Str).
x_write(Str) :-
    % We are NOT running in a Pengines instance, use write.
    !,
    write(Str).

Unfortunately, the pengine_self() call appears to be failing so I end up getting a sandbox error when my PEngines code tries to call write:

Object received:{
    "code": "permission_error",
    "data": "No permission to call sandboxed `write(_1040)'\nReachable from:\n\t  tsll:x_write(A)\n\t 

What could cause pengine_self to fail?

Also, is there a procedure or set of steps for triggering the graphical debugger when a PEngines thread executes, so I can trace PEngine hosted code?

Sandboxing is based on static analysis. As the analyser doesn’t know whether pengine_self/1 fails or not it considers both branches reachable.

AFAIK, normal write/1 does redirect in pengines as the I/O streams are redefined. Otherwise, if you want to write code that is useful in different embeddings, avoid using I/O. Especially in Prolog, this is rarely needed anyway as the toplevel provides the necessary I/O.

1 Like

Ah, good to know!

But how can you use it if the analyzer won’t let you? This confuses me.

Since I can’t figure out how to trace/debug a PEngines thread, I have to use lots of logging as a substitute. If I knew how to trace/debug a PEngines thread I would discard those write/pengine_output statements that are strictly there for debugging purposes.

If you use write/1 in normal pengine source it is automatically replaced (that is, when using SWISH). If you use it on some library called from pengines, make sure the API is safe and declare the API to be save using sandbox:safe_primitive/1.

It is a bit unclear to me which combination of swish and/or pengines you are using. When calling pengines from JavaScript, I guess one way is to load a file that defines system:trace as safe, make sure the graphical debugger is loaded and put trace in the query where you want to trace. You can play a similar trick with debug/3.

1 Like

That’s what I needed to know Jan, thanks! I’ll give that a try. I assume I should remove that code when running production and only use that technique when using a local dev instance, as a security mesaure? Interesting side question from that, is there a way to emulate conditional compilation in a Prolog source file? (IFDEF/ENDIF, etc.)

I am not using Swish for my project. Just PEngines launched by executing the swipl with the main PEngines run.pl file on the command line. The PEngines instance is a private instance running on the same box as my host Node.JS app that services public web requests. In other words, only the Node.JS is available via HTTPS requests to the world, not the PEngines instance and Swish is not running at all in this configuration.

http://www.swi-prolog.org/pldoc/man?section=conditionalcompilation

And, why use swish at all if you only need pengines? This is enough to get a pengine server:

:- use_module(library(http/http_server)).
:- use_module(library(pengines)).

server :-
    http_server([ port(5050)
                ]).
2 Likes

Thanks again Jan! (re: conditional compilation)

I don’t think I’m using Swish, am I doing that without realizing it? As I said, I launch my PEngines server by executing swipl with the Pengines run.pl file as the only command line argument. If I look at run.pl I only see this:

% ROS: Run in DEBUG mode for now.
:- debug.
:- [load].
:- server(3030).

And load.pl has this:

:- use_module(library(pengines)).
:- use_module(library(http/http_error)).
:- use_module(server).
:- use_module(storage).

:- use_module(lib/admin/admin).
:- use_module(lib/admin/server_statistics).
:- use_module(lib/admin/change_passwd).

:- if(exists_source(apps(swish/swish))).
:- multifile http:location/3.
http:location(swish, apps(swish), [priority(10)]).
:- use_module(apps(swish/swish)).
:- endif.

% ROS: TSLL
% access at /apps/tsll/index.html
:- if(exists_source(apps(tsll/app))).
:- use_module(apps(tsll/app)).
:- endif.

Ok, I see the reference to Swish in the mix. I thought I needed it to have the full PEngines Admin interface so I didn’t comment out those blocks? Is there any harm in having Swish resident?

1 Like

This pengine stuff, as I said a couple of times, is mostly outdated. If you just want pengines, use the very short program I just gave. You apparently do not want swish. You seem to want some admin stuff. What for?

2 Likes

Any time I can save myself from doing web interface work I jump on it. Apparently there is no inherent logging in PEngines, but I believe it will be much easier to add that capability and surface it in the PEngines admin screen than to do that all myself.

Also, I like the instance statistics the Admin interface provides and I also like the fact it handles the authorization for having access to the Admin feature pages. Are you saying that those features are available without having to use the (apparently) outdated older PEngines interface?

Mostly, yes. Logging has library(http/http_log) (which probably works with the Pengines admin interface). Authentication has several http libraries and Anna’s add-on. Managing pengine config can be done at runtime using set_setting/2, but typically you add the settings to a startup/config file.

For development you typically run the server interactively, so you can use the thread monitor and other tools to manage things. You can also edit files and run ?- make. to update.

1 Like

Thanks Jan. One other reason I may be using the old Pengines code is because I’m not sure how to make sure I am using the new code. I believe I seeded my PEngines code from the packages-pengines directory that is found inside the main SWI-Prolog repository. So:

  • Isn’t the packages-pengines directory inside the main SWI-Prolog repository where one finds the latest PEngines code? If not, where do I find it?

  • What is it that you saw during our discussions that makes you believe I am using the older PEngines code?

1 Like

Yes.

You are talking about run.pl and admin interfaces. packages-pengines contains neither. Just library(pengines), a few support libraries and some test code.

1 Like

I see. I need to do a full code compare to see what happened. It’s possible I grabbed the code from somewhere else. Hopefully I merged in the latest packages-pengines source files of the same name into what I seeded.

If pengine is outdated, what’s the modern replacement?

2 Likes

Pengines are not outdated. The pengines application framework is. It is not maintained and the development goes to swish. swish started as an application in the above framework, but by now replaces most its functionality and is actively being developed and maintained.

1 Like