PL_cleanup in embedded swipl

Dear developers,

I am currently trying to connect swipl to R (not like rserve_client or real, but the other way round, i.e., an R library that connects to swipl). It is still a bit rusty, but I am making some progress. However, when unloading the R library (“detaching” in R terminology), it turns out that I cannot load it again. I boiled it down to this small C++ program that embeds swipl twice (Compilation with swipl-ld example.cpp):

#include "SWI-cpp.h"
#include <iostream>

int main(int argc, char** argv)
{
  { std::cout << "1st" << std::endl ;
    PlEngine e(argc, argv) ;
  }

  { std::cout << "2nd" << std::endl ;
    PlEngine e(argc, argv) ;
  }
}

The second initialization of the “PlEngine” raises a segmentation fault. I guess this part of the documentation of PL_cleanup() is still valid:

In theory, this function allows deleting and restarting the Prolog system in the same process. In practice, SWI-Prolog’s cleanup process is far from complete, and trying to revive the system using PL_initialise() will leak memory in the best case. It can also crash the application. In this state, there is little practical use for this function. If you want to use Prolog temporarily, consider running it in a separate process. If you want to be able to reset Prolog, your options are (again) a separate process, modules or threads.

And there’s probably not much hope given the complexity of the program and the many dependencies and modules that can be attached, or is it? I will try follow the advice with the separate process.

Yes. I’m afraid this will only be resolved when there is need for it by somebody or some organization with enough resources to clean this up.

It the round trip time is not too critical that avoids a lot of trouble. @ericzinda is working on a solution to use SWI-Prolog more or less transparently as a library for Python while Prolog runs in a process. The solution is language neutral.

You could see this as a simple and more efficient alternative to Pengines for scenarios where shared usage, distribution over the network, sandboxing and isolation are not needed. Maybe you can team up?

cleaning up PL_cleanup :blush:, like that one.

I’ll contact @ericzinda, I am curious how large is the overlap. On the other hand, redoing the whole thing with Pengines could also be very instructive for me.

1 Like

I’ve pushed a large number of patches to address this issue. PL_cleanup() now seems to work, both allowing the system to be restarted after the cleanup and actually reclaiming all memory. That is, using the core Prolog system and some of the (simpler) libraries that use foreign code. Many of foreign extensions, notably xpce and library(rdf) are similar projects on their own.

The biggest advantage of this enterprise is that it found many small and a few more serious memory leaks. According to ASAN (Address Sanitizer), running the core test suite leaks no memory now. Hunting memory leaks is probably the most valuable part of this work.

Note that this is not unlikely to cause some regression due to possible wrong order of cleanup or use-after-free issues. In the long run it will surely pay of.

Also note that shutting down Prolog and reinitializing it is still mostly a bad idea as it is typically much faster to keep the system alive and use (temporary) modules to deal with different knowledge bases.

4 Likes