Lockups at program terminations

There can be several reasons why an LibCXX Widget Toolkit-using program does not properly terminate.

Problems disconnecting from the X Input Method server

LibCXX Widget Toolkit does an orderly teardown of the connection to the XIM server when the library shuts down. For troubleshooting purposes:

x::w::skip_xim_disconnect=true

This terminates the connection with the XIM server immediately.

Circular references

LibCXX Widget Toolkit uses smart pointers/reference counted objects to implement all widgets. A circular reference results in class instances of various LibCXX Widget Toolkit widgets not getting destroyed correctly. This prevents the library's internal execution thread from properly shutting down. The internal execution thread does not stop until all objects that use it get destroyed.

This chapter discusses some of the common causes of circular references and how to eliminate them.

Containers hold references to all widgets in the container

A basic widget, like a button, is owned by its container (the top level main window, or an intermediate container). Taking the button widget, and storing its parent container in the widget's appdata field creates a circular reference.

Capturing widgets in callbacks

A callback for a widget cannot capture a reference to the widget's parent or child elements. This creates an internal circular reference.

Using weak captures is often the simplest solution.

Storing widgets in static or dynamic scope
static x::w::labelptr l;

void create_tab(const &x::w::factory &f)
{
     l=f->create_label("Hello world");
}

Unless something gets rid of this statically-scoped reference to a widget, its existence will prevent LibCXX Widget Toolkit from properly shutting down. Good rules of thumb to follow:

  • All widgets get created in automatic scope. All examples in this tutorial create their x::w::main_windows in automatic scope, before creating all widgets but not directly storing them anywhere.

  • The remaining widgets get created, and generally not separately stored anywhere other than internally, by the library, in their containers.

  • Callbacks attached to widgets typically weakly capture any other elements they need. In limited, well defined, controlled cases, a callback captures a different widget in an unrelated hierarchy.