Проблема c MessageBox
От: pva  
Дата: 12.01.24 20:03
Оценка:
Привет,

что-то я потерялся в дебрях WinApi. Прошу помощи. Предистория:

https://en.cppreference.com/w/cpp/thread/mutex

lock — locks the mutex, blocks if the mutex is not available


реализация в msvc std
    void lock() {
        if (_Mtx_lock(_Mymtx()) != _Thrd_result::_Success) {
            // undefined behavior, only occurs for plain mutexes (N4950 [thread.mutex.requirements.mutex.general]/6)
            _STD _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
    ...


и я таки наступил на эти грабли в результате примерно такого кода
fn(...)
        std::unique_lock guard(sync);
    ...
    MessageBox(...)
    fn(...)
            std::unique_lock guard(sync);

Тоесть, по стеку креша я вижу что блокирующий MessageBox прокинул сообщения в WindowProc через UserCallWinProcCheckWow, что привело к рекурсии.
Как это вообще понимать? и самое главное как с этим бороться?
newbie
Re: Проблема c MessageBox
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.01.24 20:26
Оценка:
Здравствуйте, pva, Вы писали:

pva>Тоесть, по стеку креша я вижу что блокирующий MessageBox прокинул сообщения в WindowProc через UserCallWinProcCheckWow, что привело к рекурсии.

pva>Как это вообще понимать? и самое главное как с этим бороться?

Ну, вообще-то в очередь сообщение кладёт PostMessage, а SendMessage напрямую дергает WindowProc, так что, теоретически, такое вполне возможно
Маньяк Робокряк колесит по городу
Re[2]: Проблема c MessageBox
От: pva  
Дата: 12.01.24 20:38
Оценка:
Здравствуйте, Marty, Вы писали:

M>Ну, вообще-то в очередь сообщение кладёт PostMessage, а SendMessage напрямую дергает WindowProc, так что, теоретически, такое вполне возможно

Нет, там беда в другом. MessageBox(HWND_DESKTOP, ...) не блокирует ничего и нужен флаг MB_TASKMODAL в нагрузку.
newbie
Отредактировано 12.01.2024 20:41 pva . Предыдущая версия .
Re[3]: Проблема c MessageBox
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 12.01.24 21:28
Оценка:
Здравствуйте, pva, Вы писали:

M>>Ну, вообще-то в очередь сообщение кладёт PostMessage, а SendMessage напрямую дергает WindowProc, так что, теоретически, такое вполне возможно

pva>Нет, там беда в другом. MessageBox(HWND_DESKTOP, ...) не блокирует ничего и нужен флаг MB_TASKMODAL в нагрузку.

Ну, логично, если бы он десктоп заблокировал, ничего бы не работало
Маньяк Робокряк колесит по городу
Re: Проблема c MessageBox
От: reversecode google
Дата: 12.01.24 22:31
Оценка:
std::recursive_mutex
Отредактировано 13.01.2024 7:36 reversecode . Предыдущая версия .
Re[2]: Проблема c MessageBox
От: pva  
Дата: 13.01.24 10:26
Оценка:
Здравствуйте, reversecode, Вы писали:

R>std::recursive_mutex

Нет, в лучшем случае где-то в рекурсии сработает флаг, который начнет размотку, а в общем случае будет stack overflow с кучей MessageBox на экране.
newbie
Re[4]: Проблема c MessageBox
От: pva  
Дата: 13.01.24 10:28
Оценка:
Здравствуйте, Marty, Вы писали:

M>>>Ну, вообще-то в очередь сообщение кладёт PostMessage, а SendMessage напрямую дергает WindowProc, так что, теоретически, такое вполне возможно

pva>>Нет, там беда в другом. MessageBox(HWND_DESKTOP, ...) не блокирует ничего и нужен флаг MB_TASKMODAL в нагрузку.

M>Ну, логично, если бы он десктоп заблокировал, ничего бы не работало

Это не так работает. MB_TASKMODAL указывается тоже с HWND_DESKTOP. Но ведь при этом система не лочится. Рекомендую черпнуть из истоков.
Впрочем, вероятно, систему тоже можно залочить, если использовать MB_SYSMODAL.
newbie
Re: Проблема c MessageBox
От: Stanislav V. Zudin Россия  
Дата: 13.01.24 10:34
Оценка: +1
Здравствуйте, pva, Вы писали:

pva>и я таки наступил на эти грабли в результате примерно такого кода

pva>
fn(...)
pva>        std::unique_lock guard(sync);
pva>    ...
pva>    MessageBox(...)
pva>    fn(...)
pva>            std::unique_lock guard(sync);
pva>

pva>Тоесть, по стеку креша я вижу что блокирующий MessageBox прокинул сообщения в WindowProc через UserCallWinProcCheckWow, что привело к рекурсии.
pva>Как это вообще понимать? и самое главное как с этим бороться?

Я правильно понимаю, что в обработчике оконного сообщения ты вызываешь messagebox, после чего снова приходит это сообщение?
Такое бывает обычно во всяких WM_PAINT.
Обычно достаточно булевского флага на входе функции.

Если упрощенно, то что-то типа такого:

LRESULT fufelHandler(blah-blah-blah)
{
   static bool bWeAreInFunction = false;
   if (!bWeAreInFunction)
   {
      bWeAreInFunction = true;
      ...
      doSomething();
      ...
      bWeAreInFunction = false;
   }
   return 0;
}


Это то, что тебе требуется?
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Проблема c MessageBox
От: reversecode google
Дата: 13.01.24 11:07
Оценка: +1
что?
нет
тебе уже ниже написали что messagebox просто вызывает еще раз обработчик
поставь логирование что бы понять на какой ивент
в общем случае рекурсив мютексы для этого и предназначены
они работают на виндовых критических апи секциях
которые так все любят когда пишут на апи и этих проблем нет
а чистые мютексы это немного другое
Re[3]: Проблема c MessageBox
От: reversecode google
Дата: 13.01.24 11:23
Оценка:
или трекай и скипай свой меседж бокс хендл в хандлере
Re[2]: Проблема c MessageBox
От: pva  
Дата: 13.01.24 13:15
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Я правильно понимаю, что в обработчике оконного сообщения ты вызываешь messagebox, после чего снова приходит это сообщение?

SVZ>Такое бывает обычно во всяких WM_PAINT.
SVZ>Обычно достаточно булевского флага на входе функции.
...
SVZ>Это то, что тебе требуется?
Да, как вариант решения — годится. Но в данном случае хватило сделать MB блокирующим через MB_TASKMODAL.
newbie
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.