Skip to content

[Windows] Destroying a Menu or MenuItem aborts the process #54

Description

@tofutim

[Windows] Destroying a Menu or MenuItem aborts the process

What happens

On Windows, freeing a Menu or a MenuItem kills the process. It makes no difference whether Dart's
garbage collector frees the handle or the program calls dispose() itself. The abort is
0xc0000409 (fast-fail 7) in ucrtbase.dll, and stderr carries no message, unlike the click fault in
#52, which printed a clear one.

This is separate from #52 and survives the fix proposed there.

Reproduce

A small Flutter app on nativeapi-flutter 0.2.4, Flutter 3.41.2, Windows 11, release build, with the
menu opened by a real right-click. Each open builds a menu of 15 items with three submenus, so about 23
handles in total. I forced a major collection between opens to remove timing luck.

what the app does with the previous menu outcome
rebuilds each open, lets the collector free the old one dies on the second pick, 2 runs of 2
rebuilds each open, calls dispose() on the old one first dies on the second pick, 2 runs of 2
rebuilds each open, keeps every old menu alive survived 6 picks, 2 runs of 2
builds one menu and reuses it survived 6 picks, 2 runs of 2

I added prints to menu_windows.cpp to see the order. Every crashing run ends the same way, on the last
~MenuItem::Impl of the previous menu, with no further output.

Opening the menu matters too. When the app opened its own menu from a timer or a local HTTP handler, the
same build survived 48 picks. Only a real right-click, which reaches the menu through Flutter's pointer
handling, produced the crash.

A lead, offered as a guess rather than a finding

WindowMessageDispatcher::DispatchWindowProc copies the handler list, then calls the handlers with the
lock released. A menu destroyed while that copy is being walked leaves a handler pointing at an object
that is gone. That would fit what I see: destruction during menu activity, an abort with no message, and
no crash at all when nothing is ever destroyed. I have not proved it, and the trace prints do not reach
far enough to say.

Workaround for now

Build menus once and never let one be destroyed. Rebuilding is safe as long as the old menus stay alive,
though on Windows that leaks a menu handle each time.

I have a reproduction ready and I am happy to test any patch you would like to try.

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