# Ann: SWI-Prolog 10.1.10

**URL:** <https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-10/9711>\
**Category:** Releases\
**Created:** [June 25, 2026, 11:48am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-10/9711 "2026-06-25T11:48:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 25, 2026, 11:48am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-10/9711/1 "2026-06-25T11:48:50Z")

</div>

# SWI-Prolog Changelog since version 10.1.9

This is mostly a polish release. PlDoc gains an optional changelog integration that adds a _history_ section to predicate documentation, mined from the git history at build time (from version 8.0 to the current release). PlDoc also pulls the xpce reference manual into its navigation and link resolution.

A fixed heap-use-after-free in xpce seems to improve stability of the  
development tools significantly. This was discovered because it caused  
a reproducing crash in the London Tube GUI demo for zooming and panning.

A new GitHub Actions workflow publishes the Windows NSIS installer on  
every `V*` tag, preparing for SignPath-signed Windows releases (new  
SECURITY, PRIVACY and CODE\_SIGNING policies are part of that  
application).

**Highlights**

- **FIXED** (xpce): black fringes left behind when graphicals move,  
a heap-use-after-free in event dispatch, and HTML manual lookup  
for symbolic class names (`==`, `:=`, …). New  
`edit(class(Class))` to jump to built-in xpce class sources.

- **FIXED** : `PL_unify_int64()` and friends could spuriously signal  
a stack overflow. This notably affected `call_with_inference_limit/2`.

- **ENHANCED** : `call_with_inference_limit/2` no longer allocates a  
bignum for the “no limit” case, fixing it on no-bignum builds and  
reducing stack usage elsewhere.

- **ENHANCED** : `listing/2` with the `source(true)` option now  
prints the source location as a clickable URL.

- **FIXED** (ssl): `ecdsa_sign/4`, `ecdsa_verify/4` and  
`load_private_key/3` for EC keys on OpenSSL 3 (#175).

- **FIXED** (json): `domain_error(method, get)` is now raised as  
documented (#144).

- **FIXED** (swipy / C++): packaging metadata for `janus-swi` 1.5.2  
(#19) and `PlRegister` constructor arity types in the C++ binding.

**Full ChangeLog**

- ENHANCED: call\_with\_inference\_limit/2: avoid pushing a bignum for  
“no limit” This fixes this predicate for systems compiled without  
bignum support (rarely used these days) and reduces stack usage on  
systems with bignum support.

- CLEANUP: static int → bool for is\_or/del\_attr/has\_attributes\_after  
Three attvar helpers were declared static int but their bodies use  
only succeed/fail/return true/return false:

- CLEANUP: static int → bool/boolex\_t for type-test and visited helpers  
Type-test helpers used by the compiler and the cycle detector were  
declared `static int` but only ever return true or false:

- CLEANUP: type local variables holding bool returns as bool, not int  
Several local rc/rval variables hold the result of a function that  
returns bool (PL\_unify\ __, PL\_is\__ , PL\_error) but are declared int.  
This is a pure cleanup — no behaviour change. Updated sites and  
the related helpers:

- CLEANUP: type local variables holding boolex\_t as boolex\_t, not int  
Several functions return boolex\_t (true/false plus negative \*\_OVERFLOW  
codes) but callers stored the result in `int rc`. No data loss  
occurred because both happen to be the same width, but the type was  
misleading and a future change to the boolex\_t representation could  
silently break callers that switch on specific overflow codes.

- CLEANUP: consistent bool/boolex\_t typing for ensure_Space and put\__  
family User-visible fixes (only triggered on no-bignum builds,  
i.e. neither GMP nor libbf):

- FIXED: PL\_unify\_int64() and related functions may signal false stack  
overflow These functions called put\_int64() without allowing GC,  
but not handling the overflow properly.

- FIXED: prolog\_close\_source/1: close on hooked (xref) open. The xref  
hooks do not refine closing and the standard close should happen.

- BUILD: Do not try to install these .qlf files

- DOC: Merge all write predicates into one description.

- FIXED: tidg/1: meta predicate declaration.

- BUILD: Added cmake option `-DCHANGELOG=ON`

- BUILD: Make SWI-Prolog runs during build halt the build system on  
error messages

- ADDED: xref\_public\_list/3: accept a stream as input.

- ADDED: prolog\_open\_source/2, prolog\_close\_source/1 and  
prolog\_file\_directives/3 to accept a stream These predicate now  
accepts a stream as input source. This allows reading the drective  
block from a stream.

- DOC: add SECURITY, PRIVACY and CODE\_SIGNING policies; rename CoC [no  
ci] Prepares the repository for the SignPath Foundation code-signing  
application: add a security-reporting address, a privacy statement,  
and a code-signing policy describing the planned signed Windows  
release flow. Also rename Code-of-Conduct.md to CODE\_OF\_CONDUCT.md  
so GitHub’s Community Standards detect it.

- CI: extract only the Windows installer from the build container docker  
cp on newer engines refuses to write symlinks whose target escapes the  
destination, which made the whole-build.win64 copy fail on a relative  
symlink under home/app/. Switch to the tar-stream form of docker cp  
and extract only the swipl-_-_.x64.exe.

- FIXED: pkg\_doc(DEPENDS …) now applies to .tex generation, not just  
html/pdf The DEPENDS list passed to pkg\_doc() was only forwarded to  
the per-package .html / .pdf rules. The pldoc / doc2tex / txt2tex  
commands that produce the .tex files saw no such dependency, so  
e.g. packages/cql/cqldoc.tex could be built before chr was installed  
in the build home, and `library(‘cql/cql’)’ would fail to load  
library(chr/chr\_translate) at .tex-generation time.

- CI: log in to GHCR before pulling the MinGW build image Required so the  
release workflow can pull a private [Package swipl-mingw-build · GitHub](http://ghcr.io/swi-prolog/swipl-mingw-build)  
when org policy disallows public packages. Harmless once/if the  
image is made public.

- CI: add Windows installer release workflow Triggered on V\* tags  
(and manually via workflow\_dispatch), this job pulls the pre-built  
MinGW cross-compile image from GHCR, clones and builds swipl inside  
the container via the image’s --win64-from-git entrypoint mode,  
extracts the NSIS installer with docker cp, and attaches it to the  
GitHub Release for the tag.

- FIXED: Include \<poll.h\> based on HAVE\_POLL instead of HAVE\_POLL\_H  
The streams/I/O code includes \<poll.h\> guarded by HAVE\_POLL\_H,  
but decides whether to actually call poll() and use `struct pollfd`  
based on HAVE\_POLL. These come from two independent configure probes  
(check\_include\_file vs check\_function\_exists). When they disagree –  
e.g. the poll() function is detected (HAVE\_POLL) but the header probe  
for poll.h fails for an unrelated reason – \<poll.h\> is omitted while  
poll() is still compiled, producing:

- BUILD: serialise Wine swipl.exe runs via a Ninja job pool When  
cross-building for Windows on Linux, every swipl.exe step (qlf compiles,  
library indices, man index) runs under Wine through a single wineserver.  
Parallel `ninja` over-saturates wineserver, occasionally deadlocking  
client requests and hanging the build. Define a swipl\_run=1 Ninja job  
pool on the cross-build path and apply it to the custom commands that  
invoke swipl; native builds expand the JOB\_POOL keyword to nothing  
and are unaffected.

- ENHANCED: listing/2 using source(true): show source location as URL.

## Package cpp

- FIXED: PlRegister constructors must take size\_t arity to match macros  
The previous commit changed the PREDICATE/PREDICATE\_NONDET trampoline  
signatures to (term\_t, size\_t, control\_t) but left the PlRegister  
constructors taking (term\_t, int, control\_t), breaking every user of  
the macros.

- UBSAN: use size\_t instead of int for arity That is the error

## Package json

- FIXED: #144 Raise domain\_error(method, get) as promised.

## Package pldoc

- ADDED: doc\_man: integrate xpce reference manual into PlDoc Make  
xpce class members and their manual pages reachable from PlDoc:  
hook xpce into the navigation tree, resolve xpce in-page links  
(#class-… and #sec:…), render ivar object links, and add  
prolog:pldoc\_synopsis\_spec/2 to rewrite the pce\_principal synopsis  
to library(pce).

- ADDED: Add a _history_ section to a predicate block The relevant  
history facts are extracted from git. This information is collected  
at build time if the cmake option `-DCHANGELOG=ON` is given.

- ADDED: library(pldoc/doc\_changes): machine readable access to changelog.  
This library is installed when the cmake option `-DCHANGELOG=ON`  
is given. That also triggers building the database when SWI-Prolog  
is built.

## Package ssl

- TEST: regression for #175 ecdsa\_sign/4 + ecdsa\_verify/4 Sign and verify  
with a hard-coded prime256v1 SEC1 PEM key, and check that a verification  
of tampered data fails. Also asserts that load\_private\_key/3 returns  
the expected ec/3 shape, since the load\_private\_key/3 path was broken  
by the same OpenSSL 3 cleanup that broke ecdsa.

- FIXED: #175 ecdsa\_sign/4 and ecdsa\_verify/4 with OpenSSL 3 On OpenSSL  
3, ecdsa\_sign/4 always failed silently and any verification produced  
wrong results. Two bugs in the USE\_EVP\_API path:

- FIXED: load\_private\_key/3 corrupting EC keys with OpenSSL 3 In the  
USE\_EVP\_API path, unify\_ec() left priv\_bn uninitialised when passed  
to EVP\_PKEY\_get\_bn\_param(), queried OSSL\_PKEY\_PARAM\_GROUP\_NAME as  
an octet string (it is UTF-8), and never checked any return values.  
The resulting ec(Priv,Pub,Curve) term contained a garbage curve  
name and an undefined private-key field, breaking every subsequent  
ecdsa\_sign/4 and ecdsa\_verify/4 call.

## Package swipy

- FIXED: Respect `const char*` return from PyUnicode\_AsUTF8AndSize()  
Old code changed the `/` into `r` and back. Should be safe in a single  
thraeded context, but might cause problems with free threaded Python.

- FIXED: #19 pip/uv install toggling for janus-swi 1.5.2 The setup.py  
was duplicating fields already declared in pyproject.toml (author,  
author\_email, url, description, license). With recent setuptools  
this causes the generated metadata to mark them as “Dynamic: author”  
and “Dynamic: home-page” (Metadata-Version 2.2), which some pip/uv  
versions handle by writing partial RECORD files. The next install  
then complains the package is distutils-installed and cannot be  
uninstalled, producing the alternating succeed/fail pattern reported  
in packages-swipy#19 and Popper#144.

## Package xpce

- DOC: Update -\>fill references to reflect colour-only support The  
-\>fill instance variable on box, arc, arrow, circle, ellipse and  
path is implemented as a colour (with the special names foreground  
and background); image/bitmap fill patterns are no longer supported.  
The manual still described filling with images, patterns and bitmaps.

- BUILD: Fix building xpce docs when there is no display

- DOC: -\>initialise / -\>\_execute for classes \== and ?, class spatial.

- FIXED: HTML manual lookup for symbolic xpce classes (==, :=, …)  
The runtime extracts the live class name from the xpce object,  
but the HTML index and anchors are keyed on the safe file-base form  
(equal, binding, noteq, …). Map class names through classmap on  
the way out of object\_spec so manpce(==) → click on a method finds  
the matching 

- ADDED: Support `edit(class(Class))` to edit built-in xpce classes.

- FIXED: black fringes left when graphicals are moved Inflate the dirty  
rectangle reported by -\>changed\_image by 1 pixel in each direction.  
Antialiased strokes and primitives drawn at non-integer coordinates  
can paint just outside the integer bounding box; without slop, those  
pixels are not repainted when the graphical moves, leaving fringes.

- FIXED: heap-use-after-free in updatePointedDevice during event dispatch  
Use for\_chain instead of for\_cell for the three chain iterations  
in updatePointedDevice. generateEventGraphical can dispatch Prolog  
handlers that mutate the chain (e.g. an -\>expose on a connection  
removes a cell from dev-\>graphicals), which for\_cell cannot tolerate.
