You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ext/enchant: abort when PHP starts twice in a process with libenchant 2.8 #25412
ok
(process:164148): GLib-GObject-CRITICAL **: 09:58:25.468: cannot register existing type 'EnchantProvider'
(process:164148): GLib-CRITICAL **: 09:58:25.468: g_once_init_leave: assertion 'result != 0' failed
(process:164148): GLib-GObject-ERROR **: 09:58:25.468: cannot create new instance of invalid (non-instantiatable) type '<invalid>'
But I expected this output instead:
ok
ok
libenchant is written in Vala since 2.7.0 and registers GLib types the first time a broker is created. php_module_shutdown() unloads enchant.so and libenchant with it, but GLib is linked with -z nodelete and keeps these types. The next php_module_startup() loads libenchant again, which registers them a second time: GLib refuses, and creating the broker aborts.
An embedder that restarts PHP in its process hits this. I found it with FrankenPHP, which does so to restart its workers or to reload its configuration (php/frankenphp#2834): on Ubuntu 26.04, the first use of enchant after a restart kills the server.
With ZEND_DONT_UNLOAD_MODULES=1 in the environment, the program prints ok twice. The extension could keep itself loaded by dropping its handle, as OPcache does for its own, which gives the same result here:
PHP_MINIT_FUNCTION(enchant)
{
+ /* GLib keeps the types libenchant registers: the library can't be loaded twice */+ enchant_module_entry.handle = NULL;+
enchant_broker_ce = register_class_EnchantBroker();
PHP Version
PHP 8.5.12 (cli) (built: Nov 12 2026 09:52:03) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.5.12, Copyright (c) Zend Technologies
with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies
Activity