Boehm gc和多线程程序的问题
Problem with Boehm gc and mutli-thread program
我在多线程程序中使用 Boehm
垃圾收集器时遇到问题。
我的主要功能休眠,而线程正在使用垃圾收集器执行一些分配和释放。
当一个collect()
被垃圾回收器调用时,主线程的休眠被打断,程序若无其事地继续运行。
以下源代码在 1 秒后终止,但它必须至少休眠 100 秒:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define GC_THREADS
#include <gc/gc.h>
void foo () {
sleep (1);
GC_gcollect (); // or multiple allocation, that will trigger a collect at some point
}
void * thread_func (void* data) {
foo ();
}
int main () {
// GC_init (); ordinarily useless, and does not change anything
pthread_t id;
GC_pthread_create (&id, NULL, &thread_func, NULL);
sleep (100);
printf ("End \n");
}
同样的问题发生,当线程正在休眠和执行分配的主函数时。
我在 ubuntu-18.04
.
上使用 bohem gc
的最后一个稳定版本(即 8.0.4
)
有人知道发生了什么事吗?
垃圾收集器使用许多信号(根据 debugging documentation、SIGSEGV
、SIGBUS
,以及多线程上的 SIGPWR
和 SIGXCPU
linux 像你正在使用的那样在内部进行设置,并为它们设置信号处理函数。
sleep()
将在调用信号处理程序时被中断,returns 如果不被中断,则超时前剩余的秒数。如果在睡眠中触发集合,就会发生这种情况。
因此,如果您想将 sleep()
与垃圾收集器混合使用,则必须使用如下循环:
int timeout = 100;
int time_remaining;
while ((time_remaining = sleep(timeout)) > 0) {
timeout = time_remaining;
}
更健壮的实现直接使用 nanosleep()
(sleep()
是如何在 Linux+Glibc 上实现的)以获得更好的错误处理:
struct timespec req = { .tv_sec = 100, .tv_nsec = 0 };
struct timespec rem;
while (nanosleep(&req, &rem) < 0) {
if (errno == EINTR) {
// Interrupted by a signal handler
req = rem;
} else {
// Some other error happened; handle appropriately for your application
perror("nanosleep");
exit(EXIT_FAILURE);
}
}
一个更健壮的版本,由于垃圾收集器使用的时间,睡眠时间不会超过 100 秒(除非到目前为止睡眠时间 + gc 时间超过该时间)使用 clock_nanosleep()
来睡眠到给定的时间戳:
struct timespec req;
if (clock_gettime(CLOCK_MONOTONIC, &req) < 0) {
perror("clock_gettime");
exit(EXIT_FAILURE);
}
req.tv_sec += 100;
int rc;
while ((rc = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &req, NULL)) != 0) {
if (rc != EINTR) {
fprintf(stderr, "clock_nanosleep: %s\n", strerror(rc));
exit(EXIT_FAILURE);
}
}
我在多线程程序中使用 Boehm
垃圾收集器时遇到问题。
我的主要功能休眠,而线程正在使用垃圾收集器执行一些分配和释放。
当一个collect()
被垃圾回收器调用时,主线程的休眠被打断,程序若无其事地继续运行。
以下源代码在 1 秒后终止,但它必须至少休眠 100 秒:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define GC_THREADS
#include <gc/gc.h>
void foo () {
sleep (1);
GC_gcollect (); // or multiple allocation, that will trigger a collect at some point
}
void * thread_func (void* data) {
foo ();
}
int main () {
// GC_init (); ordinarily useless, and does not change anything
pthread_t id;
GC_pthread_create (&id, NULL, &thread_func, NULL);
sleep (100);
printf ("End \n");
}
同样的问题发生,当线程正在休眠和执行分配的主函数时。
我在 ubuntu-18.04
.
bohem gc
的最后一个稳定版本(即 8.0.4
)
有人知道发生了什么事吗?
垃圾收集器使用许多信号(根据 debugging documentation、SIGSEGV
、SIGBUS
,以及多线程上的 SIGPWR
和 SIGXCPU
linux 像你正在使用的那样在内部进行设置,并为它们设置信号处理函数。
sleep()
将在调用信号处理程序时被中断,returns 如果不被中断,则超时前剩余的秒数。如果在睡眠中触发集合,就会发生这种情况。
因此,如果您想将 sleep()
与垃圾收集器混合使用,则必须使用如下循环:
int timeout = 100;
int time_remaining;
while ((time_remaining = sleep(timeout)) > 0) {
timeout = time_remaining;
}
更健壮的实现直接使用 nanosleep()
(sleep()
是如何在 Linux+Glibc 上实现的)以获得更好的错误处理:
struct timespec req = { .tv_sec = 100, .tv_nsec = 0 };
struct timespec rem;
while (nanosleep(&req, &rem) < 0) {
if (errno == EINTR) {
// Interrupted by a signal handler
req = rem;
} else {
// Some other error happened; handle appropriately for your application
perror("nanosleep");
exit(EXIT_FAILURE);
}
}
一个更健壮的版本,由于垃圾收集器使用的时间,睡眠时间不会超过 100 秒(除非到目前为止睡眠时间 + gc 时间超过该时间)使用 clock_nanosleep()
来睡眠到给定的时间戳:
struct timespec req;
if (clock_gettime(CLOCK_MONOTONIC, &req) < 0) {
perror("clock_gettime");
exit(EXIT_FAILURE);
}
req.tv_sec += 100;
int rc;
while ((rc = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &req, NULL)) != 0) {
if (rc != EINTR) {
fprintf(stderr, "clock_nanosleep: %s\n", strerror(rc));
exit(EXIT_FAILURE);
}
}