Hot-restart guard comes from fox_utils 0.1.8 (shared with other media_kit apps)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-09 18:58:08 +03:00
1 parent d002ff6941
commit b2b77a6b3f
7 files changed
+9 -95

No files matched your search

-2
View File
@@ -9,7 +9,6 @@ project(runner LANGUAGES CXX)
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"hot_restart_guard.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
@@ -23,6 +22,5 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
target_link_libraries(${BINARY_NAME} PRIVATE ${CMAKE_DL_LIBS})
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
@@ -1,69 +0,0 @@
#include "hot_restart_guard.h"
#ifdef NDEBUG
void hot_restart_guard_attach(FlView* view) {}
#else
#include <dlfcn.h>
#include <stdint.h>
#include <unistd.h>
namespace {
// Mirrors media_kit's NativeReferenceHolder (debug only): a calloc'd buffer
// of kReferenceBufferSize intptr slots holding live mpv_handle addresses,
// its address written in decimal to <tmp>/<kFilePrefix><pid>.
constexpr int kReferenceBufferSize = 512;
constexpr char kFilePrefix[] = "com.alexmercerind.media_kit.NativeReferenceHolder.";
using SetWakeupCallback = void (*)(void* ctx, void (*cb)(void*), void* d);
SetWakeupCallback find_set_wakeup_callback() {
static const char* const kNames[] = {"libmpv.so.2", "libmpv.so", "libmpv.so.1"};
for (const char* name : kNames) {
void* lib = dlopen(name, RTLD_NOW | RTLD_NOLOAD);
if (lib == nullptr) continue;
auto fn = reinterpret_cast<SetWakeupCallback>(
dlsym(lib, "mpv_set_wakeup_callback"));
dlclose(lib); // Drops only the reference NOLOAD added.
if (fn != nullptr) return fn;
}
return nullptr;
}
// Runs on the engine's UI thread before the old isolate shuts down, so the
// buffer is not being written concurrently. Clearing the callback takes the
// same lock mpv calls it under: once this returns, mpv never calls it again.
// The handles stay in the buffer: media_kit's startup in the new isolate
// still sends them "quit".
void on_pre_engine_restart(FlEngine* engine, gpointer user_data) {
g_autofree gchar* name = g_strdup_printf("%s%d", kFilePrefix, getpid());
g_autofree gchar* path = g_build_filename(g_get_tmp_dir(), name, nullptr);
g_autofree gchar* contents = nullptr;
if (!g_file_get_contents(path, &contents, nullptr, nullptr)) return;
const guint64 address = g_ascii_strtoull(contents, nullptr, 10);
if (address == 0) return;
const SetWakeupCallback set_wakeup = find_set_wakeup_callback();
if (set_wakeup == nullptr) return;
const auto* slots = reinterpret_cast<const intptr_t*>(address);
int cleared = 0;
for (int i = 0; i < kReferenceBufferSize; i++) {
if (slots[i] == 0) continue;
set_wakeup(reinterpret_cast<void*>(slots[i]), nullptr, nullptr);
cleared++;
}
if (cleared > 0) {
g_message("hot restart: unhooked %d mpv wakeup callback(s)", cleared);
}
}
} // namespace
void hot_restart_guard_attach(FlView* view) {
g_signal_connect(fl_view_get_engine(view), "on-pre-engine-restart",
G_CALLBACK(on_pre_engine_restart), nullptr);
}
#endif
@@ -1,13 +0,0 @@
#ifndef RUNNER_HOT_RESTART_GUARD_H_
#define RUNNER_HOT_RESTART_GUARD_H_
#include <flutter_linux/flutter_linux.h>
// Debug builds: before a hot restart tears the Dart isolate down, unhooks
// the libmpv wakeup callbacks that media_kit's players point at that
// isolate's NativeCallables. Without this, the next mpv event on a leftover
// player calls into freed code and the process dies (SIGSEGV on mpv's
// "core" thread). No-op in profile/release.
void hot_restart_guard_attach(FlView* view);
#endif // RUNNER_HOT_RESTART_GUARD_H_
@@ -6,7 +6,6 @@
#endif
#include "flutter/generated_plugin_registrant.h"
#include "hot_restart_guard.h"
struct _MyApplication {
GtkApplication parent_instance;
@@ -88,7 +87,6 @@ static void my_application_activate(GApplication* application) {
gtk_widget_realize(GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
hot_restart_guard_attach(view);
gtk_widget_grab_focus(GTK_WIDGET(view));
}