最近的GTK 3.22仍然对Boehm GC友好吗(线程问题)?

vsdwdz23  于 2023-03-22  发布在  其他
关注(0)|答案(2)|浏览(173)

Boehm's conservative garbage collector非常有用(例如Bigloo正在使用它,Guile正在使用类似的东西,等等),特别是在Linux上(这是我唯一关心的操作系统;我使用Debian/Sid/x86-64,如果这很重要的话,libgc-dev包是1:7.4.2-8版本,所以Boehm GC是7.4.2)。
但是,Boehm的GC需要知道使用它的每个线程,它的gc_pthreads_redirects.h(或多或少内部)头文件**将pthread_create**重新定义为

# define pthread_create GC_pthread_create

实际上,Boehm的GC需要的是在新线程调用堆栈的早期调用GC_register_my_thread(GC_pthread_create正在这样做)。
在过去,Glib(2.46)提供了一种使用struct GMemVTable重新定义内存分配的方法,该方法已被弃用****并且不能再使用(我的Debian的libglib2.02.0-dev包版本为2.50.3-2)。有一个g_mem_gc_friendly全局布尔值,但当查看Glib源代码时,它只是在释放内存区域之前清除它们。
最新GTK 3(我的libgtk-3-dev包的版本为3.22.11-1)正在创建线程(对于可能与Dbus有关的内容,也可能是GtkTextView...)使用(间接地)pthread_create通过Glib thread functions。(除了通过修补源代码)被通知线程创建。我恐怕比任何GTK回调我会安装(例如使用g_signal_connect)可能会从这些线程调用。或者如果我用一些可能使用(或访问)一些GC_malloc-ed缓冲区的方法子类化一个GTK小部件,可能会有灾难。
另一方面,GTK中有一个强大的编码规则,所有GTK操作都应该只在主线程中发生。引用Gdk3 Threads页面:

GTK+,但是****不是 * 线程安全**。您应该仅从调用gtk_init()gtk_main()的线程使用GTK+和GDK。这通常被称为“主线程”。

如果我自己遵循这个规则,我确信没有内部GTK代码会从一些非主线程调用我的回调(使用Boehm GC)?
我的直觉是,如果X1 m15n1x被GTK内部从主线程外部调用(而不是直接被我的代码调用),就会发生灾难(因为这些GTK内部线程没有用GC_pthread_create启动;可能会调用我的一些代码,例如,因为我正在子类化一些现有的GTK小部件,或者因为我连接了一些GTK信号,即使我自己没有在主线程之外使用GTK和Boehm GC编写代码。
关键是Boehm的GC需要扫描可能使用它的每个线程中的每个堆栈。
顺便说一句,我在GTK bugzilla上报告了一个可能的bug#780815
一个典型的例子是来自GTK-3.22.11 tarball的gtk+-3.22.11/examples/application9/

lb3vh1jj

lb3vh1jj1#

Gtk不会从非主线程调用任何信号处理程序。您在Gtk应用程序中发现的任何工作线程都通过消息队列与主线程交互。您可以在Glib源代码中看到这一点。例如,请参阅g_dbus_connection_signal_subscribe的实现()schedule_callbacks()gdbusconnection.c中。(工作线程调用g_source_attach(...,subscriber-〉context),其中第二个参数是**g_main_context_ref_thread_default()返回的参数。)
所以你不需要用
g_mem_set_vtable()**覆盖内存分配例程。如果你以前这样做过,那是一个非常糟心的设计,你用一个自动但不完美(和不稳定)的内存管理方案Boehm GC取代了GLib/Gtk中完美的手动内存管理实现。

vlf7wbxs

vlf7wbxs2#

最近的GTK 3.22仍然对Boehm GC友好吗(线程问题)?


据我所知,GTK对Boehm GC从来都不是特别友好,最近的版本似乎也不是。
我的GTK 2和GTK 3安装中的所有GTK共享库都是动态链接到libpthread的,这告诉我,尽管它们可能不都直接调用pthreads函数,但它们至少都依赖于一个这样做的库。因此,有充分的理由认为GTK或一个密切相关的库(如GLib)将在某些情况下启动内部线程。同时,没有一个库是动态链接到libgc的,所以我们可以非常确信GTK启动的内部线程不会在GC中注册自己。
我没有深入了解任何内部线程可以做什么,但有很好的理由认为它们有时会存储和访问指向客户端应用程序提供的对象的指针,这为过早收集通过GC_malloc()分配的此类对象打开了一扇门。(因此,现在不推荐的对注入自定义分配器的支持永远不足以使GTK应用程序成为GC安全的。)这与您的观察基本相同:
关键是Boehm的GC需要扫描可能使用它的每个线程中的每个堆栈。
这也与the GC docs一致:
通常最好不要将垃圾收集分配与系统malloc-free混合使用。如果这样做,则需要注意不要将指向垃圾收集堆的指针存储在与系统malloc一起分配的内存中。
此外,这意味着这个问题没有实际意义:
如果我[避免调用gtk和gdk函数而不是从主线程],我确信没有内部GTK代码会从一些非主线程调用我的回调(使用Boehm GC)?
即使我们(合理地)假设内部线程永远不会调用应用程序回调,这并不意味着GC忽略它们的堆栈、线程本地存储或每个线程的内存分配是安全的。
但是为了回答这个问题,回调函数可以调用GTK函数是GTK与程序员的合同的一部分。因为这应该只在主线程中完成,所以我希望回调函数只在主线程中被调用。我没有找到正式的文档,但它也在the issue you raised against GTK的注解线程中被Assert。
我的直觉是,如果GTK内部从主线程外部调用GC_alloc(而不是直接由我的代码调用),就会发生灾难[],因为这些GTK内部线程没有使用GC_pthread_create [...]启动。
这是有道理的,但我认为可以安全地假设这种情况不会由GTK调用回调引起,但是,如前所述,这不足以使GTK对GC友好。
在某些系统上,你可以通过合适的动态链接器策略强制GTK使用GC_pthread_createGC_mallocGC_reallocGC_free来代替它们的标准对应物。有些系统还可以提供特殊的工具来在运行时替换分配函数。我认为这些方法可以使GC与Gtk / GLib结合使用变得安全,虽然这些组件不会从中受益。但我不会称之为“友好”的任何方向。

相关问题