Skip to content

ext/enchant: abort when PHP starts twice in a process with libenchant 2.8 #25412

Open

Description

@nicolas-grekas

Description

The following code, built against the embed SAPI and run with extension=enchant in php.ini:

#include <sapi/embed/php_embed.h>

int main(int argc, char **argv)
{
	for (int i = 0; i < 2; i++) {
		PHP_EMBED_START_BLOCK(argc, argv)
		zend_eval_string("enchant_broker_init(); echo \"ok\\n\";", NULL, "repro");
		PHP_EMBED_END_BLOCK()
	}

	return 0;
}

Resulted in this output, and the process aborts:

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

Same on master (bc2d2fc).

Operating System

Ubuntu 26.04, with libenchant 2.8.2 and GLib 2.88.0

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions