Уже всю голову сломал, Хотя проблема вроде тривиальная.
Предположим система предоставляет такие API:
Receive(context); // blocking call until external event or Close
Close(context);
Close
снимает с receive.
Есть функция потока и деструктор, который должен этот поток остановить :
thread() {
while (!stop) {
// ... (code 1)
Receive(context);
// ... (code 2)
}
}
~() {
stop = true;
Close(context);
}
Деструктор должен дождаться завершения потока. Но как это сделать?
Ирония в том что если послать Close когда поток будет в состоянии (code1)
, то вызов Receive всё равно повиснет на бесконечном ожидании внешнего события.
Значит нужно послать Close или в состоянии Receive
или в состоянии (code 2)
.
Но как гарантировано дождаться входу в функцию Receive.
Если вставить mutex и разблокировать его перед Receive, то состояние гонки всё ещё актуально ( между разблокировкой mutex и вызовом Receive может вызваться преславутый Close).
Найденный мной вариант решения проблемы - греть процессор :
thread() {
Lock
while (!stop) {
// ... (code 1)
Receive(context);
Unlock
// ... (code 2)
Lock
}
}
~() {
stop = true;
while !Try_lock() {
Close(context);
}
}
Таким образом из деструктора я буду долбить Close
пока не попаду в code(2)
. И всё бы хорошо, но Close падает с segmentation fault на повторном вызове, и это ломает всю концепцию.