Skip to content

Cleaner crash after running for a while #225

@esiqveland

Description

@esiqveland

It seems like scheduling lots of lambdas to run with GLib.idleAdd(GLib.PRIORITY_DEFAULT_IDLE crashes after a while.

This crash occurs after about 10 minutes in the given sample code:

counter: 7820
counter: 7830
counter: 7840
counter: 7850
java.lang.IllegalStateException: Session is acquired by 1 clients
	at java.base/jdk.internal.foreign.MemorySessionImpl.alreadyAcquired(MemorySessionImpl.java:306)
	at java.base/jdk.internal.foreign.SharedSession.justClose(SharedSession.java:84)
	at java.base/jdk.internal.foreign.MemorySessionImpl.close(MemorySessionImpl.java:232)
	at java.base/jdk.internal.foreign.ArenaImpl.close(ArenaImpl.java:50)
	at io.github.jwharm.javagi.interop.Arenas.close_cb(Arenas.java:66)
	at org.gnome.gio.Application.run(Application.java:1146)
	at com.github.subsound.debug.DebugGtkMemoryIssue.main(DebugGtkMemoryIssue.java:27)
Unrecoverable uncaught exception encountered. The VM will now exit

Show a crash after about 8k iterations.

The sample code frequently updates a GtkScale to simulate a updating progressbar.

public class DebugGtkMemoryIssue {
    public static void main(String[] args) {
        Application app = new Application("com.scale.example", ApplicationFlags.DEFAULT_FLAGS);
        app.onActivate(() -> onActivate(app));
        app.onShutdown(() -> {
            System.out.println("app.onShutdown: exit");
        });
        app.run(args);

    }

    private static void onActivate(Application app) {
        var cancelled = new AtomicBoolean(false);
        Button btn = Button.builder().setLabel("Cancel worker").build();
        btn.onClicked(() -> {
            System.out.println("btn.onClicked: cancel!");
            cancelled.set(!cancelled.get());
        });

        var scale1 = Scale.builder().setOrientation(Orientation.HORIZONTAL).build();
        scale1.setRange(0, 100);
        scale1.setShowFillLevel(true);
        scale1.setFillLevel(1);

        var counter = new AtomicInteger();
        var fill = new AtomicInteger();
        Thread.startVirtualThread(() -> {
            while (true) {
                if (cancelled.get()) {
                    System.out.println("worker: canceled after %d".formatted(counter.get()));
                    return;
                }
                var count = counter.addAndGet(1);
                if (count % 10 == 0) {
                    System.out.println("counter: %d".formatted(count));
                }
                int i = fill.addAndGet(1);
                var fillLevel = i % 100;

//                GLib.idleAddOnce(() -> {
//                    scale1.setFillLevel(fill.get());
//                    scale1.setShowFillLevel(true);
//                });
                GLib.idleAdd(GLib.PRIORITY_DEFAULT_IDLE, () -> {
                    scale1.setFillLevel(fillLevel);
                    // changing fill level does not always redraw the scale component,
                    // but scale.getAdjustment().emitValueChanged() forces a redraw:
                    scale1.getAdjustment().emitValueChanged();
                    return GLib.SOURCE_REMOVE;
                });

                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        var toolbar = new HeaderBar();
        // Pack everything together, and show the window
        Box box = Box.builder().setSpacing(10).setOrientation(Orientation.VERTICAL).build();
        box.append(toolbar);
        box.append(btn);
        box.append(scale1);

        var window = ApplicationWindow.builder()
                .setApplication(app)
                .setDefaultWidth(1000)
                .setDefaultHeight(700)
                .setContent(box)
                .build();

        window.present();
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions