Поскольку вся моя работа происходит в рабочих потоках, я хочу уничтожать рабочие потоки, когда возникает какой-то критический момент. ресурс недоступен. Это позволяет мне эффективно писать код, не обрабатывая повсюду ошибки. Например, мне нужно выделить немного памяти в куче. Для этого я могу вызвать «malloc», но «malloc» может вернуть nullptr, и вместо того, чтобы обрабатывать его каждый раз, когда я хочу выделить память, я просто хочу убить поток. Ниже приведен пример кода
Код: Выделить всё
void BlockMainThread () noexcept; // Wait on a semaphore
void ReleaseMainThread () noexcept; // Release the semaphore
int gExitStatus = 0;
bool gShouldRun = true;
[[noreturn]]
void
KillThread (int pExitStatus) noexcept
{
gExitStatus = pExitStatus;
ReleaseMainThread ();
pthread_exit (nullptr); // Calls __forced_unwind internally
}
void *
Malloc (int pSize) noexcept
{
void * ptr = malloc (pSize);
if (!ptr)
KillThread (1);
return ptr;
}
void *
ThreadFunc (void *) noexcept // Executed by ALL worker threads
{
printf ("Thread Started\n");
while (gShouldRun) { // Do work till time to exit
char * ptr = (char *) Malloc (100000);
// Operate on ptr without needing to worry about ptr being NULL
free (ptr);
}
return nullptr;
}
int
main ()
{
pthread_t tid1;
pthread_t tid2; // And so on
pthread_create (&tid1, nullptr, ThreadFunc, nullptr); // And so on
BlockMainThread ();
gShouldRun = false; // Stop the loop on which threads are spinning
pthread_join (tid1, nullptr); // Join with all threads
if (gExitStatus == 0) // All was good
return 0;
// Else log a message depending on the gExitStatus
printf ("Something went wrong");
return gExitStatus;
}
Однако pthread_exit означает бросок исключения 'abi::__forced_unwind'. И это исключение — это то, что необходимо повторно выбросить, если оно будет обнаружено (следовательно, нет смысла его перехватывать). И из-за этого вызывается std::terminate (поскольку мои функции — noException). Это не позволяет основному потоку регистрировать, что пошло не так.
Если функции НЕ отмечены параметром noException, поток завершается, и основной поток продолжит работу, как ожидалось.
Это происходит только в ОС Linux. Один и тот же код НЕ выдает исключение при использовании в ядре Apple и Android.
Вопросы:
- Есть ли что-нибудь Могу ли я предотвратить std::terminate при вызове pthread_exit внутри функции noException?
- Могу ли я вообще использовать noException, если хочу использовать эту модель?
- Существуют ли какие-либо обходные пути для Linux, позволяющие имитировать поведение Apple и Android для конкретных платформ?
[*]Различия платформ: В Linux pthread_exit использует __forced_unwind для раскручивания и очистки стека, что вызывает исключение. Это не относится к Apple и Android, где pthread_exit не предполагает выдачу исключений.
[*]Обработка исключений: исключение __forced_unwind является особенным и должно распространяться через кадры стека, не будучи перехваченным, поскольку оно перехватывается. и отказ от повторного создания может привести к неопределенному поведению.
[*]Управление ресурсами: цель состоит в том, чтобы аккуратно завершить рабочие потоки, не усложняя обработку ошибок в каждом распределении или критическом разделе.
Подробнее здесь: https://stackoverflow.com/questions/787 ... -functions
Мобильная версия