В настоящее время я пытаюсь реализовать потоки, используя 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;
}
Это работает более или менее, как ожидалось. Единственное, в чем я не уверен, так это в том, что очистка работает нормально.
Кажется, что функция очистки вызывается более одного раза (строка «Пойманный сигнал ..» появляется более одного раза на терминале). Есть ли способ предотвратить это? Это проблематично?
Я нашел более одного примера очистки потоков APR после использования. Достаточно ли моего пути или мне нужно кое-что прокомментировать? Или я совершенно не прав?
Очистка потока APR подробно описана в раздел резьбы из APR Tutorial. По порядку шаги очистки выглядят так:
apr_thread_exit()
в самой теме. В то время как потоки Unix завершаются автоматически, потоки Windows — нет. Вызовите эту функцию для переносимости (и для возврата статуса, если необходимо).apr_thread_join()
в главном потоке ждать завершения всех потоков.apr_pool_destroy()
освободить основной пул памяти. (Дочерние пулы памяти освобождаются с помощью apr_thread_exit()
.)apr_terminate()
освободить другие ресурсы (сокеты и т. д.). Обратите внимание, что просто звонить exit()
в другой теме без этих последних шагов может вызвать сбои.У них также есть краткая программа-пример это демонстрирует некоторые из этих вещей.
Что касается того, почему ваш обработчик сигнала срабатывает дважды, я не думаю, что это связано с APR. SIGINT отправляется на родительский и дочерний процессы, поэтому я подозреваю MyServer
создает новый процесс, и оба вызывают обработчик.
Других решений пока нет …