How DingTalk Fixed FlutterEngine Crashes, Memory Leaks, and Deadlocks on Desktop
This article details the technical challenges DingTalk faced when integrating Flutter across macOS and Windows desktops, covering memory leaks, shutdown deadlocks, OpenGL crashes, rendering glitches, plugin registration wild‑pointer crashes, and white‑screen issues, and explains the root causes and concrete solutions applied to each problem.
FlutterEngine Mac Issues
1.1 Memory Leak after FlutterEngine Exit
When the FlutterViewController is destroyed on macOS, the memory allocated by the underlying FlutterEngine is not released, leading to a leak.
Root cause: The FlutterEngine holds a weak reference to the FlutterViewController while the controller strongly holds the engine; during deallocation the weak property becomes nil, preventing proper cleanup.
Solution: Manually invoke FlutterEngine::shutDownEngine in the controller's dealloc and ensure the shutdown sequence follows the correct order (FlutterView shutdown → engine shutdown).
1.2 Shutdown Deadlock
Calling shutDownEngine before the FlutterView has been shut down caused a deadlock between the UI and Raster threads.
Root cause: The engine shutdown was triggered without first stopping the rendering pipeline via FlutterView::shutdown.
Solution: Invoke FlutterView::shutdown to stop rendering, then call FlutterEngine::shutDownEngine.
1.3 Low‑Version macOS OpenGL Crash
On older macOS versions (10.11, 10.12) the OpenGL renderer crashed during the destruction phase.
Root cause: Premature release of OpenGL objects combined with incomplete protection in the macOS OpenGL implementation.
Solution: Remove the step that nulls the FlutterView on macOS versions prior to 10.14; keep only the view shutdown and engine shutdown steps.
FlutterEngine Windows Issues
2.1 Win7 Rendering Crash and Ghosting
On some Windows 7 devices the application crashed with d3d11 errors and displayed ghosting artifacts.
Root cause: Custom soft‑render mode introduced a wild pointer in the rendering path, and the plugin registration logic left stale engine references.
Solution: Adjust the engine cleanup to null the pointer to FlutterWindowsEngine only after the view is fully destroyed, preventing raster thread callbacks to freed memory.
2.2 FlutterPlugin Registration Wild‑Pointer Crash
During plugin registration the application frequently crashed due to a wild pointer.
Root cause: The wrapper layer’s PluginRegistrarManager was not a true singleton; each plugin DLL contained its own instance, leaving stale engine pointers after engine destruction.
Solution: Refactor PluginRegistrarManager to a genuine singleton managed at the lower layer, ensuring proper cleanup of registrar bindings.
2.3 Window Visibility Change White Screen
When a Flutter window is hidden and then shown again, the content remains blank until a manual refresh is triggered.
Root cause: The Windows implementation does not flush the rendering pipeline after a visibility change.
Solution: After native window visibility changes, manually notify Flutter to refresh the current page, forcing a redraw.
Conclusion
Across the desktop platforms, DingTalk’s experience shows that while Flutter v2.10 adds official Windows support, macOS remains more stable. Teams planning to adopt Flutter for desktop should prioritize macOS for better performance and reliability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
