Когда windows сигнализирует о дескрипторе процесса? - PullRequest
6 голосов
/ 22 января 2009

У меня реализован процесс самостоятельного обновления, когда мое основное приложение exe запускает программу обновления, передавая дескриптор себе в командной строке. Затем exe приложения вызывает ExitProcess для выхода, а средство обновления вызывает WaitForSingleObject для переданного дескриптора, чтобы дождаться завершения exe приложения.

WaitForSingleObject действительно ждет. До тех пор, пока приложение не вызовет ExitProcess, программа обновления останавливается.

Однако иногда, когда средство обновления пытается перезаписать dll приложения новыми версиями, я получаю сообщение об ошибке блокировки файла, которое текущая версия моего средства обновления рассматривает как неисправимую и завершает. Кажется, что включение произвольного сна (100) достаточно, чтобы обойти эту «проблему», но я действительно ненавижу такой код. действительно ненавижу.

Мне кажется очень странным, что дескриптор процесса может сигнализироваться, пока основное приложение еще достаточно активно, чтобы блокировать dll-файлы.

Ответы [ 6 ]

2 голосов
/ 22 января 2009

Процесс сигнализирует о выходе кода приложения. ОС может занять немного больше времени, чтобы полностью выгрузить процесс. Смысл сигнализации состоит в том, чтобы сказать: «Я сделал то, что мне нужно», более эффективно выпускать другой код, который может содержать действительно полезные вещи, вместо того, чтобы заставлять этот код ждать, пока ОС выполняет некоторые служебные обязанности. *

1 голос
/ 10 марта 2009

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

Вы правы, полагая, что сон (100) - плохая идея. Вы должны вместо этого перезаписать свои библиотеки DLL в цикле следующим образом:

BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) {
  int tries = 150;
  while (tries--) {
    if (TryUpdateDll(dll_name, whatever))
      return TRUE;
    Sleep(200);
  }
  return FALSE;
}

Это продолжает пытаться выгрузить вашу DLL в течение 30 секунд, а затем сдается. 30 секунд должно быть достаточно, даже если система находится под большой нагрузкой, но все равно защитит ваш апдейтер от зависания навсегда. (В случае, если UpdateDll возвращает FALSE, убедитесь, что предоставили осмысленное сообщение об ошибке своему пользователю с указанием имени вызывающей DLL).

Если вы возитесь с COM, вызов CoFreeUnusedLibraries перед выходом также может быть полезен. (http://msdn.microsoft.com/en-us/library/ms679712.aspx) Честно говоря, я не знаю, может ли COM удерживать библиотеки DLL даже после завершения вашего процесса, но лучше быть в безопасности.

Суть в том, что в Win32 API много странностей. Вам не нужно заниматься каждым делом, пока вы можете найти приемлемое решение. Очевидно, что Sleep (100) может нарушиться, но 30-секундные циклы опроса кажутся мне приемлемыми.

0 голосов
/ 09 марта 2009

возможное исправление для вас ... хотя вы не можете заменить используемую dll, вы можете переименовать ее. так что если у вас есть dll, который нужно заменить, но по какой-то причине он используется, переименуйте его в .delete или что-то в этом роде. выполните обновление, а затем попросите основную программу выполнить поиск файлов .delete и удалить их при запуске.

-don

0 голосов
/ 09 марта 2009

Если какая-либо из используемых вами DLL-библиотек использует потоки, они могут не завершать (или объединять) достаточно быстро, если вы явно не выгружаете их - что, конечно, произойдет, если вы явно загрузили их с помощью LoadLibrary

Взгляните сюда: http://msdn.microsoft.com/en-us/library/ms682596(VS.85).aspx

В частности, эта строка:

... DLL выгружается при процесс завершается или вызывает Функция FreeLibrary и ссылка количество становится равным нулю. Если процесс заканчивается в результате TerminateProcess или TerminateThread функция, система не вызывает Функция точки входа DLL.

0 голосов
/ 06 марта 2009

Около шести месяцев назад увидел несколько таких антивирусных программ. Попробуйте без AV и, по крайней мере, убедитесь, что AV обновлен.

0 голосов
/ 28 января 2009

Возможно, что библиотеки DLL заблокированы каким-то другим процессом в то время. Один из способов проверить это - создать отчет о том, что удерживает DLL, когда это произойдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...