APR线程和信号处理

4
我目前正在尝试使用Apache Portable Runtime实现线程。除了缺乏文档或示例,一切都运行正常,但我不确定是否按照预期进行操作。
我需要两个线程和信号处理来捕获控制台上的CTRL-C以清理我的服务器和可能的线程。这是我目前的方法:
// Define APR thread pool
apr_pool_t *pool;

// Define server
MyServer *server;

// Define threads
apr_thread_t *a_thread, *b_thread;
apr_status_t status;

static void * APR_THREAD_FUNC func_a(apr_thread_t * thread,
        void *data) {
        // do func_a stuff here
}

static void * APR_THREAD_FUNC func_b(apr_thread_t * thread,
        void *data) {
        // do func_b stuff here
}

// Cleanup before exit
void cleanup(int s) {
    printf("Caught signal %d\n", s);

    // Destroy thread pool
    apr_pool_destroy(pool);

    //apr_thread_exit(a_thread, APR_SUCCESS);
    //apr_thread_exit(b_thread, APR_SUCCESS);

    //apr_terminate();

    // Stop server and cleanup
    server->stopServer();
    delete server;

    exit(EXIT_SUCCESS);
}

int main(void) {
    // Signal handling
    signal(SIGINT, cleanup);

    // Create server
server = MyServerFactory::getServerImpl();

bool success = server->startServer();

// Initialize APR
if (apr_initialize() != APR_SUCCESS) {
    printf("Could not initialize\n");
    return EXIT_FAILURE;
}

// Create thread pool
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
    printf("Could not allocate pool\n");
    return EXIT_FAILURE;
}

// Create a_thread thread
if (apr_thread_create(&a_thread, NULL, func_a, NULL,
        pool) != APR_SUCCESS) {
    printf("Could not create a_thread\n");
    return EXIT_FAILURE;
}

//Create b_thread thread
if (apr_thread_create(&b_thread, NULL, func_b, NULL,
        pool) != APR_SUCCESS) {
    printf("Could not create b_thread\n");
    return EXIT_FAILURE;
}

    // Join APR threads
    apr_thread_join(&status, a_thread);
    apr_thread_join(&status, b_thread);

    return EXIT_SUCCESS;
}

这个工作基本符合预期。唯一不确定的是清理是否正常运行。
  1. 清理函数似乎被调用了多次(终端上出现了多次“Caught signal…”字符串)。有没有办法防止这种情况?这会有问题吗?

  2. 我找到了多个清理APR线程使用的例子。我的方法足够了吗,还需要一些注释掉的内容吗?或者我完全错了?


我遇到了同样的问题。我找不到任何文档或示例来解决这个问题。 - ant2009
1个回答

0

APR线程清理在APR教程线程部分中有详细的解释。按顺序,清理步骤如下:

  1. 在线程本身中调用apr_thread_exit()。虽然Unix线程会自动终止,但Windows线程不会。为了可移植性(以及返回状态,如果必要),调用此函数。
  2. 在主线程中调用apr_thread_join()等待所有线程的终止。
  3. 调用apr_pool_destroy()释放主内存池。(子内存池使用apr_thread_exit()释放。)
  4. 调用apr_terminate()释放其他资源(套接字等)。请注意,仅在另一个线程中调用exit()而没有这些最后一步可能会导致崩溃

他们还有一个简短的示例程序演示了其中的一些内容。

关于为什么你的信号处理程序会触发两次,我认为这与 APR 无关。SIGINT 会发送给父进程和子进程,所以我怀疑 MyServer 正在分叉一个新进程,两个进程都在调用处理程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接