Циклы WaitForSingleObject и while в C /

#c #mutex #waitforsingleobject

#c #мьютекс #waitforsingleobject

Вопрос:

Вот фрагмент: prog1:

 HANDLE hM;
hM = CreateMutexA(NULL,TRUE, "abc"); // I have to use TRUE otherwise WaitForSingleObject fails.. by design it wants to take ownership and w//o TRUE there is no owner anyway right? <<-- **check this please if its true**
...
  

prog2:

 HANDLE hM;
hM = OpenMutexA(MUTEX_ALL_ACCESS,NULL, "abc");
while(WaitForSingleObject(hM,INFINITE)) {
// do smthing
ReleaseMutex(hM);
hM = OpenMutexA(MUTEX_ALL_ACCESS,NULL, "abc"); // In order to continue while loop but it doesnt rewind,
}
  

Проблема> Это не приведет к созданию полубесконечного цикла … он вводится один раз, и все.

Цель? Чтобы отслеживать активность какого-либо процесса (если он выходит из строя, я перезапускаю его), бесконечные циклы сильно ударяют по моему процессору, и я не могу использовать Sleep, мне нужно перезапустить его asasp (хорошо, если возможно какое-то разумное решение через while(1) или for(;;), пожалуйста, опубликуйте)

Обновить

должно быть while(WaitForSingleObject(hM, БЕСКОНЕЧНЫЙ) == WAIT_ABANDONED){ … }, я неправильно скопировал :).

Он работает один раз, а затем больше не будет ждать, есть ли способ сбросить дескриптор?


prog1:

 HANDLE hM;
hM = CreateMutexA(NULL,TRUE, "abc");
  

prog2:

 HANDLE hM;
hM = OpenMutexA(MUTEX_ALL_ACCESS,NULL, "abc");
while(WaitForSingleObject(hM,INFINITE)) {    
ReleaseMutex(hM);
Sleep(1000);
CloseHandle(hM)
// do smthing like CreateProcess()
Sleep(1000);
hM = OpenMutexA(MUTEX_ALL_ACCESS,NULL, "abc");
}
  

Таким образом, это работает, если кто-то хочет что-то добавить, прокомментируйте этот пост.

Комментарии:

1. Это правда 🙂 но вы должны быть немного опытными, чтобы перейти на полный Юникод

2. Просто любопытно, какой опыт для этого потребуется?

Ответ №1:

Чтобы обнаружить сбой процесса, вам не нужно беспокоиться о мьютексе. Просто дождитесь дескриптора процесса. Как только процесс завершится, дескриптор получит сигнал и WaitForSingleObject вернется.

Если вы создаете процесс, вы можете получить дескриптор процесса из PROCESS_INFORMATION аргумента. Затем просто используйте:

 PROCESS_INFORMATION pi;

do {
// create the process, passing pi as the last argument to CreateProcess
} while (WaitForSingleObject(pi.hProcess, INFINITE));
  

Обратите внимание, что дескриптор должен быть закрыт, вы можете определить, когда.


Обновление — Учитывая, что это не вариант, вот проблема в вашем коде:

Скажем, prog1 успешно запущен, и prog2 теперь ожидает сигнала о мьютексе. Затем prog1 выходит из строя, и prog2 становится владельцем мьютекса. Учитывая, что целью prog2 является перезапуск prog1, я предполагаю, что это то, что происходит внутри // do smthing . Итак, теперь prog1 запускается и вызывает CreateMutexA . Но prog2 все еще может содержать мьютекс, и поэтому prog1 получает только дескриптор существующего мьютекса, но на самом деле он ему не принадлежит. Теперь prog2 вызывает ReleaseMutex и продолжает ожидание сигнального мьютекса, который не принадлежит prog1. Ожидание немедленно возвращается с WAIT_OBJECT_0 помощью, и вы выходите из while .

Итак, я думаю, что prog1 использует CreateMutexA здесь неправильно. Вместо этого вы должны создать не принадлежащий мьютекс и ждать его. Таким образом, вы гарантируете, что мьютекс принадлежит prog1.

Комментарии:

1. На самом деле код не так прост, как я его опубликовал. Это довольно сложно, и да, я использовал это, но на данный момент единственным решением является либо мьютекс, либо подход с разделяемой памятью. Так что постарайтесь помочь в его eran.

2. ОК. Соответствующим образом обновил мой ответ.

3. БОЖЕ, это может сработать. Проверьте этот поток еще раз, пожалуйста, я сейчас тестирую это как сумасшедший :). Вы хотите, чтобы я создал if() в prog1 и сначала ждал там или использовал FALSE флаг в этой единственной строке?

4. Хммм… Тем не менее, гонка все еще продолжается. Если prog1 создает мьютекс, то prog2 освобождает его и сразу переходит к ожиданию, прежде чем prog1 это сделает, он все равно завершится. Требуется дальнейшее обдумывание, возможно, вам придется использовать два мьютекса.

5. Использование двух объектов синхронизации не так сложно. Рассмотрите возможность использования именованного события : попросите prog2 создать его без сигнализации после ReleaseMutex и дождаться его, а prog1 открыть и сообщить об этом событии после того, как ему принадлежит мьютекс (т. Е. После Вызова WaitForSingleObject ). Таким образом, prog2 перейдет к while (WaitForSingleObject) только после того, как prog1 получит право собственности на мьютекс.

Ответ №2:

Я согласен с мнением Эрана о том, что вы должны просто ждать непосредственно в дескрипторе процесса.

Что касается того, почему ваш код не входит в while цикл, когда вы считаете, что это должно быть достаточно легко понять. while Цикл завершается, когда WaitForSingleObject возвращается 0. То есть, когда он возвращается WAIT_OBJECT_0 , или, другими словами, когда он приобрел право собственности на мьютекс. Это происходит, когда предыдущий владелец освобождает его.

Комментарии:

1. Кроме того, поскольку вы взяли на себя часть ответа на фактический вопрос ;), стоит упомянуть, что второй вызов OpenMutexA в prog2 является избыточным. Нет причин открывать уже открытый мьютекс.

2. Второй вызов заключается в том, чтобы «обмануть» цикл while для перезапуска и повторного ожидания, что работало, когда я имел дело с дескрипторами OpenProcess и process из CreateProcess.

3. И я думаю, что это не WAIT_OBJECT_0, а WAIT_ABANDONED

4. WAIT_ABANDONED не равно нулю, и в этом случае условие while будет выполнено. Единственный способ завершить while — это когда WaitForSingleObject возвращает WAIT_OBJECT_0 == 0 .

Ответ №3:

Вам не нужно повторно открывать мьютекс. WaitForSingleObject становится владельцем, а ReleaseMutex освобождает владельца, но мьютекс остается открытым, пока вы не вызовете CloseHandle .

Комментарии:

1. Я пробовал это, ReleaseMutex CloseHandle, а затем «материал». В конце я бы снова вызвал OpenMutexA. Он не будет работать так, как я хочу, он войдет в while() и выйдет из него. Я снова открываю мьютекс только для того, чтобы обмануть цикл while для продолжения, но без кубиков, надеюсь, вы понимаете.