Не удаляется Mutex
hMutex = CreateMutex(NULL, TRUE, "1234");
есть бесконечный цикл в потоке:
{
....
HANDLE m_hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234");
if (!m_hMutex) break;
}
при некоторых обстоятельствах хочу тормознуть поток, убивая мутекс:
{
ReleaseMutex(m_App->hMutex);
CloseHandle(m_App->hMutex);
}
мутекс почему то не убивается и в отладчике видно что в цикле m_hMutex != hMutex
как побороть?
Return Values
If the function succeeds, the return value is a handle to the mutex object.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
If a named mutex does not exist, the function fails and GetLastError returns ERROR_FILE_NOT_FOUND.
Не потому ли, что OpenMutex просто создает еще один описатель того же объекта ядра и соотвественно увеличивает его счетчик. А объект реально уничтожается только после того, как счетчик обнулится.
Не потому ли, что OpenMutex просто создает еще один описатель того же объекта ядра и соотвественно увеличивает его счетчик. А объект реально уничтожается только после того, как счетчик обнулится.
The OpenMutex function opens an existing named mutex object.
Все правильно. Открывает существующий объект ядра (один объект), создавая для него новый описатель. Поэтому видимо и m_hMutex и hMutex имеют разные значения.
и смысл тогда в этом, если каждый раз новые "описатели" она будет возвращать?
ЗЫ: If the function succeeds, the return value is a handle to the mutex object. Хендл объекта все время его жизни постоянен... иначе затеряется в памяти и свищи его потом
примерный перевод: "Ф-я OpenMutex открывает существующий именованный флаг"
т.е. если я его удаляю (вне потока), то он прекращает существование, следовательно в потоке ф-я OpenMutex должна возвратить NULL, т.к. объект не существует
Вызов CloseHandle не удаляет объект. Он лишь уменьшает счетчик числа его пользователей. И только если этот счетчик обнуляется, объект удаляется.
Вот в этой точке кода
{
ReleaseMutex(m_App->hMutex);
CloseHandle(m_App->hMutex);
}
я уже могу насчитать два описателя объекта мьютекса. Один - это m_App->hMutex, который вероятно был получен где-то ранее вызовом CreateMutex. Второй - это описатель полученный вот в этой строке if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234")), который вы кстати нигде не сохраняете. Плюс, если ваш поток с бесконечным циклом уже запущен, то каждая итерация цикла это еще один описатель. И пока вы ВСЕ эти описатели не закроете, объект не удалится.
{
public:
HANDLE hMutex;
};
void App::SomFunc (void)
{
this->hMutex = CreateMutex(....)
}
{
App *m_App;
....
};
void SomeClass::SomeFunc(vod)
{
if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234"))
{
ReleaseMutex(m_App->hMutex);
CloseHandle(m_App->hMutex);
}
}
ЗЫ: и пофиг совершенно сколько указателей создается... если я объекту через любой указатель говорю уничтожиться, то он по идее должен уничтожиться, а остальные указатели пусть указывают на пустое место
Не имеет значения. Суть в том, что вот этой строкой if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234")) вы создали еще один описатель. И пока вы в своем коде не закроете и его, любой последующий вызов OpenMutex будет давать положительный результат.
Use the CloseHandle function to close the handle. The system closes the handle automatically when the process terminates. The mutex object is destroyed when its last handle has been closed.
В рамках одного процесса для синхронизации лучше использовать CriticalSection, а не глоб. объекты синхронизации.
Ну а че ж тогда через CloseHandle он не убивается?
ЗЫ: вобще то проблему решил другим способом, но в се равно вопрос интересный
Для того, чтобы mutex уничтожился необходимо, чтобы каждый открытый handle был закрыт.
Элементарно сравнить два значения. Они же отличаются, не так ли? ;)
собственно и этого и начал :cool::
теперь жажду обоснования этого от МСДН
Выдержку из MSDN не нашел, но вот вам реальный пример простейшего работающего кода
HANDLE h1 = OpenMutex(MUTEX_ALL_ACCESS, NULL, "1234");
//Вот в этом месте h и h1 имеют РАЗНЫЕ значения, потому как
//"OpenMutex возвращает новый хендл"
CloseHandle(h);
HANDLE h3 = OpenMutex(MUTEX_ALL_ACCESS, NULL, "1234");
//Этот вызов завершится успешно, потому как несмотря на то, что мы
// "закрыли" h, h1 все еще не "закрыт" и объект существует.
Кстати, вполне возможно, что h3 и h буду иметь одинаковые числовые значения, но это ничего не значит, просто после вызова CloseHandle(h); строка в таблице описателей процесса освободится и ее место займет h3.
тоже самое (один в один) из CreateMutex
Каждая из функций возвращает разные handle'ы для доступа к одному и тому же системному объекту. Исходя из цитат: каждый handle должен быть закрыт. Вывод: если остается хотя бы один - объект не уничтожается, иначе была бы нестабильная работа приложений, т.к. OpenMutex мог быть вызван просто из другого потока.