.globl _state .globl _state_end _state: .incbin "state" _state_end:
Now include this as follows:
#include <SWI-Prolog.h> #if __linux #define STATE _state #define STATE_END _state_end #else #define STATE state #define STATE_END state_end #endif extern unsigned char STATE[]; extern unsigned char STATE_END[]; int main(int argc, char **argv) { if ( !PL_set_resource_db_mem(STATE, STATE_END - STATE) || !PL_initialise(argc, argv) ) PL_halt(1); return PL_toplevel(); }
As Jose Morales pointed at https://github.com/graphitemaster/incbin, which contains a portability layer on top of the above idea.
PL_CLEANUP_NO_RECLAIM_MEMORY
- Do not reclaim memory. This is the default when called from PL_halt() for the release versions because the OS will do so anyway.
PL_CLEANUP_NO_CANCEL
- Do not allow Prolog and foreign halt hooks to cancel the cleanup.
The return value of PL_cleanup() is one of the following:
PL_CLEANUP_CANCELED
- A Prolog or foreign halt hook cancelled the cleanup. Note that some of the halt hooks may have been executed.
PL_CLEANUP_SUCCESS
- Cleanup completed successfully. Unless
PL_CLEANUP_NO_RECLAIM_MEMORY
was specified this implies most of the memory was reclaimed and Prolog may be reinitialized in the same process using PL_initialise(). PL_CLEANUP_FAILED
- Cleanup failed. This happens if the user requested to reclaim all memory but this failed because the system was not able to join all Prolog threads and could therefore not reclaim the memory.
PL_CLEANUP_RECURSIVE
- PL_cleanup() was called from a hook called by the cleanup process.
PL_cleanup() allows deleting and restarting the Prolog system in the same process. In versions older than 8.5.9 this did not work. As of version 8.5.9, it works for the basic Prolog engine. Many of the plugins that contain foreign code do not implement a suitable uninstall handler and will leak memory and possibly other resources. Note that shutting Prolog down and renitializing it is slow. For almost all scenarios there are faster alternatives such as reloading modified code, using temporary modules, using threads, etc.
if ( (pid=fork()) == 0 ) { PL_cleanup_fork(); <some exec variation> }
The call behaves the same on Windows, though there is probably no meaningful application.
FALSE
if exit was cancelled by PL_cleanup().
12.4.25.1 Threading, Signals and embedded Prolog
This section applies to Unix-based environments that have signals or multithreading. The Windows version is compiled for multithreading, and Windows lacks proper signals.
We can distinguish two classes of embedded executables. There are small C/C++ programs that act as an interfacing layer around Prolog. Most of these programs can be replaced using the normal Prolog executable extended with a dynamically loaded foreign extension and in most cases this is the preferred route. In other cases, Prolog is embedded in a complex application that---like Prolog---wants to control the process environment. A good example is Java. Embedding Prolog is generally the only way to get these environments together in one process image. Java VMs, however, are by nature multithreaded and appear to do signal handling (software interrupts).
On Unix systems, SWI-Prolog installs handlers for the following signals:
- SIGUSR2
- has an empty signal handler. This signal is sent to a thread after
sending a thread-signal (see
thread_signal/2).
It causes blocking system calls to return with
EINTR
, which gives them the opportunity to react to thread-signals.In some cases the embedded system and SWI-Prolog may both use
SIGUSR2
without conflict. If the embedded system redefinesSIGUSR2
with a handler that runs quickly and no harm is done in the embedded system due to spurious wakeup when initiated from Prolog, there is no problem. If SWI-Prolog is initialised after the embedded system it will call the handler set by the embedded system and the same conditions as above apply. SWI-Prolog's handler is a simple function only chaining a possibly previously registered handler. SWI-Prolog can handle spuriousSIGUSR2
signals. - SIGINT
- is used by the top level to activate the tracer (typically bound to control-C). The first control-C posts a request for starting the tracer in a safe, synchronous fashion. If control-C is hit again before the safe route is executed, it prompts the user whether or not a forced interrupt is desired.
- SIGTERM, SIGABRT and SIGQUIT
- are caught to cleanup before killing the process again using the same signal.
- SIGSEGV, SIGILL, SIGBUS, SIGFPE and SIGSYS
- are caught by to print a backtrace before killing the process again using the same signal.
- SIGHUP
- is caught and causes the process to exit with status 2 after cleanup.
The --no-signals option can be used to inhibit all
signal processing except for SIGUSR2
. The handling of SIGUSR2
is vital for dealing with blocking system call in threads. The used
signal may be changed using the --sigalert=NUM option
or disabled using --sigalert=0
.