Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Не удаляется Mutex

11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
создаю мутекс:

hMutex = CreateMutex(NULL, TRUE, "1234");


есть бесконечный цикл в потоке:
 
Код:
while (true)
{
....
  HANDLE m_hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234");
  if (!m_hMutex) break;

}


при некоторых обстоятельствах хочу тормознуть поток, убивая мутекс:

 
Код:
if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234"))
{
  ReleaseMutex(m_App->hMutex);
  CloseHandle(m_App->hMutex);
}


мутекс почему то не убивается и в отладчике видно что в цикле m_hMutex != hMutex

как побороть?
288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Таким образом вы поток не тормознете. Если открываемого мьютекса не существует, то OpenMutex вернет ERROR_FILE_NOT_FOUND (что кстати отлично от нуля), так что if (!m_hMutex) break; никогда не выполнится.
11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: nikitozz
Таким образом вы поток не тормознете. Если открываемого мьютекса не существует, то OpenMutex вернет ERROR_FILE_NOT_FOUND (что кстати отлично от нуля), так что if (!m_hMutex) break; никогда не выполнится.




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.

288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Ох ты. Точно. Не внимательно прочитал MSDN. Извиняюсь.
288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Как бы опять глупость не сказать. ))
Не потому ли, что OpenMutex просто создает еще один описатель того же объекта ядра и соотвественно увеличивает его счетчик. А объект реально уничтожается только после того, как счетчик обнулится.
11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: nikitozz
Как бы опять глупость не сказать. ))
Не потому ли, что OpenMutex просто создает еще один описатель того же объекта ядра и соотвественно увеличивает его счетчик. А объект реально уничтожается только после того, как счетчик обнулится.



The OpenMutex function opens an existing named mutex object.

288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: oxotnik333
The OpenMutex function opens an existing named mutex object.



Все правильно. Открывает существующий объект ядра (один объект), создавая для него новый описатель. Поэтому видимо и m_hMutex и hMutex имеют разные значения.

11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: nikitozz
Все правильно. Открывает существующий объект ядра (один объект), создавая для него новый описатель. Поэтому видимо и m_hMutex и hMutex имеют разные значения.


и смысл тогда в этом, если каждый раз новые "описатели" она будет возвращать?

ЗЫ: If the function succeeds, the return value is a handle to the mutex object. Хендл объекта все время его жизни постоянен... иначе затеряется в памяти и свищи его потом

288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Объект ядра один. Hadle - это лишь "указатель" на него. И OpenMutex - действительно создает новый "указатель" на уже созданный объект. А смысл в том, что Mutex создавался для использования несколькими процессами, поэтому и создается новый Handle при вызове OpenMutex. Насколько я понял OpenMutex не делает проверку на то, имеется ли в таблице описателей текущего процесса описатель на открываемый мьютекс, а просто добавляет в таблицу новую запись. И объект уничтожится лишь тогда, когда для всех описателей будет вызван CloseHandle (ну или завершится процесс).
11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: oxotnik333
The OpenMutex function opens an existing named mutex object.


примерный перевод: "Ф-я OpenMutex открывает существующий именованный флаг"
т.е. если я его удаляю (вне потока), то он прекращает существование, следовательно в потоке ф-я OpenMutex должна возвратить NULL, т.к. объект не существует

288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Английский мне переводить не обязательно. Учил вроде ))
Вызов CloseHandle не удаляет объект. Он лишь уменьшает счетчик числа его пользователей. И только если этот счетчик обнуляется, объект удаляется.
Вот в этой точке кода
 
Код:
if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234"))
{
  ReleaseMutex(m_App->hMutex);
  CloseHandle(m_App->hMutex);
}

я уже могу насчитать два описателя объекта мьютекса. Один - это m_App->hMutex, который вероятно был получен где-то ранее вызовом CreateMutex. Второй - это описатель полученный вот в этой строке if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234")), который вы кстати нигде не сохраняете. Плюс, если ваш поток с бесконечным циклом уже запущен, то каждая итерация цикла это еще один описатель. И пока вы ВСЕ эти описатели не закроете, объект не удалится.
11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
 
Код:
class App
{
  public:
  HANDLE hMutex;
};
void App::SomFunc (void)
{
   this->hMutex = CreateMutex(....)
}
есть другой класс который имеет указатель на экземпляр App
Код:
class SomeClass
{
App *m_App;
....
};

void SomeClass::SomeFunc(vod)
{
   if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234"))
   {
      ReleaseMutex(m_App->hMutex);
      CloseHandle(m_App->hMutex);
   }
}
т.о. ReleaseMutex и CloseHandle обращаются к одному и тому же хэндлу мутекса.

ЗЫ: и пофиг совершенно сколько указателей создается... если я объекту через любой указатель говорю уничтожиться, то он по идее должен уничтожиться, а остальные указатели пусть указывают на пустое место
288
03 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: oxotnik333
т.о. ReleaseMutex и CloseHandle обращаются к одному и тому же хэндлу мутекса.



Не имеет значения. Суть в том, что вот этой строкой if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234")) вы создали еще один описатель. И пока вы в своем коде не закроете и его, любой последующий вызов OpenMutex будет давать положительный результат.

3
03 сентября 2008 года
Green
4.8K / / 20.01.2000
nikitozz прав.

Цитата:

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, а не глоб. объекты синхронизации.

11
03 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
2 Green
Ну а че ж тогда через CloseHandle он не убивается?

ЗЫ: вобще то проблему решил другим способом, но в се равно вопрос интересный
12K
04 сентября 2008 года
lifs
163 / / 06.09.2007
Так nikitozz писал
Цитата:
я уже могу насчитать два описателя объекта мьютекса. Один - это m_App->hMutex, который вероятно был получен где-то ранее вызовом CreateMutex. Второй - это описатель полученный вот в этой строке if (OpenMutex(MUTEX_ALL_ACCESS, FALSE, "1234")), который вы кстати нигде не сохраняете.



Для того, чтобы mutex уничтожился необходимо, чтобы каждый открытый handle был закрыт.

11
04 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Дайте плз выдержку из МСДН где написано что OpenMutex возвращает новый хендл, а не тот который был создан при помощи CreateMutex. Я че то не нашел.
5
04 сентября 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: oxotnik333
Дайте плз выдержку из МСДН где написано что OpenMutex возвращает новый хендл, а не тот который был создан при помощи CreateMutex. Я че то не нашел.

Элементарно сравнить два значения. Они же отличаются, не так ли? ;)

11
04 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: hardcase
Элементарно сравнить два значения. Они же отличаются, не так ли? ;)



собственно и этого и начал :cool::

Цитата: oxotnik333
]мутекс почему то не убивается и в отладчике видно что в цикле m_hMutex != hMutex



теперь жажду обоснования этого от МСДН

288
04 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: oxotnik333
Дайте плз выдержку из МСДН где написано что OpenMutex возвращает новый хендл, а не тот который был создан при помощи CreateMutex. Я че то не нашел.



Выдержку из MSDN не нашел, но вот вам реальный пример простейшего работающего кода

 
Код:
HANDLE h = CreateMutex(NULL, FALSE, "1234");
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.
12K
04 сентября 2008 года
lifs
163 / / 06.09.2007
Цитата про OpenMutex:
Цитата:
The handle can be duplicated by using the DuplicateHandle function. 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.


тоже самое (один в один) из CreateMutex

Цитата:
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.


Каждая из функций возвращает разные handle'ы для доступа к одному и тому же системному объекту. Исходя из цитат: каждый handle должен быть закрыт. Вывод: если остается хотя бы один - объект не уничтожается, иначе была бы нестабильная работа приложений, т.к. OpenMutex мог быть вызван просто из другого потока.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог