Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

infinoted will hang after config reload because the types cannot be registered after plugin reload #31

Open
pkern opened this issue Jan 15, 2023 · 3 comments

Comments

@pkern
Copy link
Contributor

pkern commented Jan 15, 2023

When infinoted receives a SIGHUP it will reload its configuration. This involves unloading and subsequently reloading all plugins. Unfortunately if note-text had been in use before and you reload the plugin, it will attempt to re-register the type the next time someone opens a document:

[Thu Jan 12 10:44:32 2023] WARNING: GLib-GObject: cannot register existing type 'InfTextBuffer'
[Thu Jan 12 10:44:32 2023]   ERROR: GLib-GObject: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
[Thu Jan 12 10:44:32 2023]   ERROR: GLib: g_once_init_leave: assertion 'result != 0' failed
[Thu Jan 12 10:44:32 2023] WARNING: GLib-GObject: cannot register existing type 'InfTextDefaultBuffer'
[Thu Jan 12 10:44:32 2023] WARNING: GLib-GObject: cannot add private field to invalid (non-instantiatable) type '<invalid>'
[Thu Jan 12 10:44:32 2023]   ERROR: GLib-GObject: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed

This hangs the I/O loop completely and no client can connect anymore and SIGTERM does not work anymore either.

@pkern
Copy link
Contributor Author

pkern commented Jan 15, 2023

I guess we'd either need to not reload that plugin (but why do others work?) or implement the dynamic TypePlugin system with a refcount? It turns out that there's already the following TODO in the code:

  /* Note that this kills all sessions with that particular type. This is
   * typically not wanted when reloading a plugin in which case a plugin is
   * deinitialized and then re-initialized. */
  /* TODO: To fix this, we should add a plugin API to reload its parameters
   * without unloading and reloading the whole plugin. */

I think this would also require to deinitialize libinftext properly? I wonder why it is reinitialized at all.

Backtrace with G_DEBUG=fatal-warnings:

(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff783bc46 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff78227fc in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7f9ae65 in infinoted_log_handler
    (log_domain=log_domain@entry=0x7ffff7eb6000 "GLib-GObject", log_level=log_level@entry=18, message=message@entry=0x5555555fd8a0 "cannot register existing type 'InfTextBuffer'", user_data=user_data@entry=0x5555555a5ab0) at /build/libinfinity-qxkwOg/libinfinity-0.7.2/infinoted/infinoted-log.c:123
#6  0x00007ffff7d975e2 in g_logv (log_domain=0x7ffff7eb6000 "GLib-GObject", log_level=G_LOG_LEVEL_WARNING, format=<optimized out>, args=<optimized out>)
    at ../../../glib/gmessages.c:1393
#7  0x00007ffff7d97893 in g_log
    (log_domain=log_domain@entry=0x7ffff7eb6000 "GLib-GObject", log_level=log_level@entry=G_LOG_LEVEL_WARNING, format=format@entry=0x7ffff7ebf2b8 "cannot register existing type '%s'") at ../../../glib/gmessages.c:1462
#8  0x00007ffff7ea779d in check_type_name_I (type_name=0x7ffff43f5f65 "InfTextBuffer") at ../../../gobject/gtype.c:769
#9  0x00007ffff7eae217 in g_type_register_static
    (parent_type=0x8 [None], type_name=0x7ffff43f5f65 "InfTextBuffer", info=info@entry=0x7fffffffbd30, flags=flags@entry=G_TYPE_FLAG_NONE) at ../../../gobject/gtype.c:2815
#10 0x00007ffff7eae474 in g_type_register_static_simple
    (parent_type=parent_type@entry=0x8 [None], type_name=<optimized out>, class_size=class_size@entry=152, class_init=class_init@entry=0x7ffff43e5e60 <inf_text_buffer_default_init>, instance_size=instance_size@entry=0, instance_init=instance_init@entry=0x0, flags=G_TYPE_FLAG_NONE) at ../../../gobject/gtype.c:2783
#11 0x00007ffff43e4b71 in inf_text_buffer_get_type () at /build/libinfinity-qxkwOg/libinfinity-0.7.2/libinftext/inf-text-buffer.c:44
#12 0x00007ffff7fbb4b3 in infinoted_plugin_note_text_session_read
    (storage=0x5555555b4450, io=0x555555577a80, manager=0x55555559f860, path=0x555555608b90 "/New Document", user_data=<optimized out>, error=0x7fffffffbf30)
    at /build/libinfinity-qxkwOg/libinfinity-0.7.2/infinoted/plugins/infinoted-plugin-note-text.c:80
#13 0x00007ffff7f581dc in infd_directory_node_make_session.constprop.0 (directory=0x5555555ba0b0, node=0x5555555bb6a0, error=0x7fffffffbf30) at server/infd-directory.c:5085
#14 0x00007ffff7f48da4 in infd_directory_handle_subscribe_session (error=0x7fffffffbf08, xml=0x5555555fcca0, connection=0x5555555dd120, directory=0x5555555ba0b0)
    at server/infd-directory.c:6100
#15 infd_directory_communication_object_received (object=<optimized out>, connection=0x5555555dd120, node=0x5555555fcca0) at server/infd-directory.c:8888
#16 0x00007ffff7f2813c in inf_communication_central_method_received (method=0x5555555cd360, connection=0x5555555dd120, xml=0x5555555fcca0)
    at communication/inf-communication-central-method.c:332
#17 0x00007ffff7f2c9c5 in inf_communication_registry_received_cb (connection=<optimized out>, xml=<optimized out>, user_data=<optimized out>)
    at communication/inf-communication-registry.c:354
#18 0x00007ffff7e86f60 in g_closure_invoke (closure=0x5555555eb3d0, return_value=0x0, n_param_values=2, param_values=0x7fffffffc240, invocation_hint=0x7fffffffc1c0)
    at ../../../gobject/gclosure.c:832
#19 0x00007ffff7eb5014 in signal_emit_unlocked_R.isra.0
    (node=node@entry=0x5555555d9600, detail=detail@entry=0, instance=instance@entry=0x5555555dd120, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffc240) at ../../../gobject/gsignal.c:3867
#20 0x00007ffff7ea512a in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffc400)
    at ../../../gobject/gsignal.c:3549
#21 0x00007ffff7ea53b3 in g_signal_emit (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>) at ../../../gobject/gsignal.c:3606
#22 0x00007ffff7f24832 in inf_xmpp_connection_process_end_element (name=0x5555555e2d0d "group", xmpp=0x5555555dd120) at common/inf-xmpp-connection.c:2706
#23 inf_xmpp_connection_sax_end_element (context=<optimized out>, name=0x5555555e2d0d "group") at common/inf-xmpp-connection.c:2845
#24 0x00007ffff7793355 in xmlParseEndTag1 (line=0, ctxt=0x5555555dc930) at ../../parser.c:8722
#25 xmlParseEndTag1.constprop.0 (ctxt=0x5555555dc930, line=0) at ../../parser.c:8681
#26 0x00007ffff779f03f in xmlParseTryOrFinish.isra.0 (ctxt=0x5555555dc930, terminate=0) at ../../parser.c:11654
#27 0x00007ffff7672243 in xmlParseChunk__internal_alias
    (ctxt=0x5555555dc930, chunk=chunk@entry=0x7fffffffc720 "<group publisher=\"you\" name=\"InfDirectory\"><subscribe-session seq=\"3\" id=\"1\"/></group>", size=<optimized out>, size@entry=86, terminate=terminate@entry=0) at ../../parser.c:12358
#28 0x00007ffff7f22e2b in inf_xmpp_connection_received_cb (tcp=<optimized out>, data=<optimized out>, len=<optimized out>, user_data=<optimized out>)
    at common/inf-xmpp-connection.c:3263
#29 0x00007ffff7adae2e in ffi_call_unix64 () at ../src/x86/unix64.S:105
#30 0x00007ffff7ad7493 in ffi_call_int (cif=<optimized out>, fn=<optimized out>, rvalue=<optimized out>, avalue=<optimized out>, closure=<optimized out>)
    at ../src/x86/ffi64.c:672
#31 0x00007ffff7e8d6b0 in g_cclosure_marshal_generic_va
    (closure=<optimized out>, return_value=<optimized out>, instance=<optimized out>, args_list=<optimized out>, marshal_data=<optimized out>, n_params=<optimized out>, param_types=<optimized out>) at ../../../gobject/gclosure.c:1650
#32 0x00007ffff7ea52cc in _g_closure_invoke_va
--Type <RET> for more, q to quit, c to continue without paging--
    (param_types=<optimized out>, n_params=<optimized out>, args=0x7fffffffd390, instance=<optimized out>, return_value=<optimized out>, closure=0x5555555dc410)
    at ../../../gobject/gclosure.c:895
#33 g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffd390)
    at ../../../gobject/gsignal.c:3456
#34 0x00007ffff7ea53b3 in g_signal_emit (instance=<optimized out>, signal_id=signal_id@entry=46, detail=detail@entry=0) at ../../../gobject/gsignal.c:3606
#35 0x00007ffff7f1c6ab in inf_tcp_connection_io_incoming (connection=connection@entry=0x5555555a1e10) at common/inf-tcp-connection.c:666
#36 0x00007ffff7f1d000 in inf_tcp_connection_io (socket=<optimized out>, events=INF_IO_INCOMING, user_data=<optimized out>) at common/inf-tcp-connection.c:812
#37 0x00007ffff7f1a507 in inf_standalone_io_iteration_impl (io=io@entry=0x555555577a80, timeout=<optimized out>, timeout@entry=-1) at common/inf-standalone-io.c:413
#38 0x00007ffff7f1b09d in inf_standalone_io_loop (io=0x555555577a80) at common/inf-standalone-io.c:1184
#39 0x000055555555cdb0 in infinoted_run_start (run=run@entry=0x5555555a58a0) at ./infinoted/infinoted-run.c:482
#40 0x000055555555a6d5 in infinoted_main_run (error=0x7fffffffde20, startup=<optimized out>) at ./infinoted/infinoted-main.c:148
#41 infinoted_main (error=0x7fffffffde10, argv=<optimized out>, argc=<optimized out>) at ./infinoted/infinoted-main.c:192
#42 main (argc=<optimized out>, argv=<optimized out>) at ./infinoted/infinoted-main.c:216

@pkern
Copy link
Contributor Author

pkern commented Jan 15, 2023

Ok, my suspicion that this is because the static variable that keeps track of the type's initialization gets thrown out makes sense: g_module_close calls dlclose which is documented to:

All shared objects that were automatically loaded when dlopen() was invoked on the object referred to by handle are recursively closed in the same manner.

And the "once" variable is part of the library.

There's no other reference on libinftext so that library gets unloaded as well and thus it will try to reinit itself when reloaded, which glib bails out on.

@pkern
Copy link
Contributor Author

pkern commented Jan 15, 2023

(Thus an easy but unclean solution would be to force linkage from infinoted to libinftext.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant