Информация об изменениях

Сообщение Re[3]: Когда же винда научится извлекать устройства? от 10.01.2024 12:50

Изменено 10.01.2024 12:55 Pavel Dvorkin

Re[3]: Когда же винда научится извлекать устройства?
Здравствуйте, Sinclair, Вы писали:

S>Ага, то есть когда я делаю ShutDown, то договориться можно, а когда Eject — то нет?

S>Вот от тебя, Павел, я такого не ожидал.

Зря не ожидал. Извини за большое цитирование. Все из Соломона-Руссиновича. Выделено мной

Остановка службы
Когда Winlogon вызывает Windows-функцию ExitWindowsEx, эта функция от-
правляет сообщение Csrss — процессу подсистемы Windows — для вызова
Csrss-процедуры завершения работы. Csrss осуществляет циклический перебор
активных процессов и уведомляет их, что система завершает работу. Для каж-
дого системного процесса, за исключением SCM, Csrss ждет несколько секунд,
количество которых определено параметром HKU\.DEFAULT\Control PanelDesktop\WaitToKillAppTimeout (по умолчанию 20 с), пока не будет осуществлен
выход из процесса, после чего переходит к следующему процессу. Когда Csrss
встречает процесс SCM, он также уведомляет его о завершении работы системы,
но использует лимит времени, определенный для SCM. Csrss распознает SCM,
используя идентификатор процесса, который Csrss сохранил при регистрации
SCM с Csrss с помощью функции RegisterServicesProcess в ходе инициализа-
ции системы. Лимит времени для SCM отличается от лимита других процессов,
поскольку Csrss знает, что SCM обменивается данными со службами, которым
при остановке нужно осуществить подчистку после своей работы. Поэтому ад-
министратору может понадобиться настроить только лимит времени, выделяе-
мый SCM. Параметр лимита времени SCM находится в разделе реестра HKLMSYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout и по умолчанию
составляет 12 секунд.
Обработчик остановки SCM отвечает за рассылку уведомлений всем службам,
запросившим уведомление об остановке при своей инициализации с помощью
SCM. SCM-функция ScShutdownAllServices осуществляет циклический перебор
записей служб в базе данных SCM в поиске служб, желающих получить уведомле-
ние об остановке, и отправляет каждой из них команду на остановку. Для каждой
службы, которой отправляется команда на остановку, SCM записывает параметр,
указывающий время ожидания службы, значение которого служба также определяет
при своей регистрации с помощью SCM. SCM отслеживает самое продолжительное
указанное время ожидания. После отправки сообщений об остановке SCM ждет,
либо пока одна из служб, которая была оповещена об остановке, не осуществит
выход, либо пока не пройдет самое продолжительное указанное время.
Если указанное время истечет, а служба не осуществит выход, SCM определя-
ет, не отправила ли одна или несколько служб, от которых ожидался выход, со-
общение SCM о том, что эта служба находится в процессе своей остановки. Если
хотя бы одна служба продвинулась в этом процессе, SCM снова ждет истечения
установленного времени ожидания. SCM продолжает выполнение этого цикла
ожидания, пока либо все службы не осуществят выход, либо ни одна из служб,
в отношении которых осуществляется ожидание, не уведомит его о нахождении
в процессе свой остановки за тот период времени, который указан для ожидания.
Пока SCM занимается отправкой приказов службам на остановку и ожида-
нием их выхода, Csrss ждет выхода от SCM. Если ожидание, осуществляемое
Csrss, заканчивается до того, как будет осуществлен выход SCM (по истечении
времени, указанного в параметре WaitToKillServiceTimeout), Csrss принудительно
завершает работу SCM и продолжает процесс завершения работы системы. Таким
образом, службы, давшие сбой при остановке за отведенное для этого время,
останавливаются принудительно. Такая логика позволяет системе завершать
работу вопреки тем службам, которые никогда не остановятся в результате де-
фектов своей конструкции
, но это также означает, что службы, требующие более
20 секунд, не завершат своих действий по остановке.
Кроме того, поскольку порядок остановки ничем не обусловлен, службы,
которые могут зависеть от других служб, для своей первоочередной остановки
не имеют способа сообщить об этом SCM, могут не иметь никаких шансов на
подчистку после своей работы.
В связи с этими потребностями в Windows реализуются предостановочные
уведомления и порядок остановки для противодействия проблемам, вызывае-
мым этими двумя сценариями. Предостановочные уведомления рассылаются
с использованием того же механизма, который используется для уведомлений
об остановке. Уведомления рассылаются тем службам, которые запросили предостановочные
уведомления посредством API-функции SetServiceStatus, и SCM
будет ждать от них подтверждения.
Идея, заложенная в этих уведомлениях, заключается в пометке тех служб,
у которых на подчистку может уйти много времени (это, к примеру, может
касаться служб сервера базы данных), и в выделении им большего количества
времени на завершение их работы. SCM отправит запрос на выяснение хода про-
цесса и будет 3 минуты ждать завершения работы тех служб, которые на него
ответили. Если служба за это время не ответит, она будет принудительно оста-
новлена в рамках процедуры завершения работы системы; в противном случае
она может продолжать свое выполнение столько времени, сколько потребуется,
пока она будет продолжать отвечать на запросы SCM.
Службы, участвующие в предварительной остановке (preshutdown), могут
также определить порядок остановки по отношению к другим службам, также
участвующим в предварительной остановке. Службы, зависящие от первооче-
редной остановки других служб (например, Group Policy должна дождаться
завершения работы службы обновления Windows Update), могут указать свои
зависимости от остановок других служб в параметре реестра HKLM\SYSTEMCurrentControlSet\Control\PreshutdownOrder.


Так что здесь намного сложнее. Если коротко — Windows при определенных условиях убивает сервисы при shutdown. Там это можно, все равно помирать. А тут нельзя. Иначе может рухнуть все зависимое от этого сервиса. Только с его согласия. А это есть — SERVICE_CONTROL_STOP


PD>>Вот, к примеру, сделаю я программу, которая делает fopen, а потом этот хендл не закрывает. Сидит в памяти, чем-то занимается, процессор загружает в среднем на 0%, а хендл не закрывает.

PD>>Как ее попросить ? Никак.
S>Повторюсь: несколько похожих задач были успешно решены примерно во времена Win7.

Ну не знаю, что именно было решено. Механизм этот ЕМНИП не менялся.

S>В частности, при шатдауне винда прекрасно строит список "несогласных", показывает их мне, и даже даёт выбор между "дать шанс закончиться добровольно" и "пристрелить к такой-то матери".


См. выше.

S>В частности, при гибернейте твоя программа прекрасно "отпустит" диск, так что его можно будет извлечь с нулевым риском для его файловой системы.

S>Ну, только после пробуждения твоя программа словит ошибку обращения к диску — но это уже будет проблема этой программы (или пользователя, если он реально хотел, чтобы она всё-таки файл сохранила).

Так и сейчас совсем не обязательно, что если ты выдернешь флешку, с ее ФС будут проблемы. Ну не пишет, допустим, моя программа туда сейчас.
А при Hibernate все программы остановлены, так что точно не пишет. Ну а потом...

PD>>Windows не имеет права прибивать хендлы процесссов. Это имеет право делать только пользователь, берущий тем самым на себя ответственность за последствия.

S>Ну так дайте такую возможность пользователю. Что за детский сад?
PD>>Программ таких, принудительно закрывающих хендлы файлов, немало
S>Если бы они нормально работали...

Да в общем, работают. Использовал не раз.

PD>>https://udalenie-fajlov.softok.info/


PD>>Ну и сюда посмотри


PD>>https://serverfault.com/questions/1966/how-do-you-find-what-process-is-holding-a-file-open-in-windows

S>Смотрел. Почему не сделать это штатной фичей винды?

Потому что рискованно. Эти программы ты запускаешь на свой страх и риск, и MS ни за что не отвечает, если ты их используешь. А дай такую штатную возможность — закроет юзер все хендлы твоего любимого MS SQL именно в то время, когда он там что-то перестраивает, а потом начнутся вопли — где моя БД ?

PD>>Сделаю я из нее сервис, а то, о чем написал, так и оставлю.

S>Даже если не делать сервис — как думаешь, в какой версии винды появилось сообщение WM_QUERYENDSESSION?

Точно не знаю, но в 3.0 уже было.
Да, это запрос на согласие закончиться при окончании сессии.

Для сервисов аналоги — SERVICE_ACCEPT_STOP (можно остановить) и SERVICE_ACCEPT_SHUTDOWN (получает уведомление при завершении работы системы).


Но никто не мешает программе потом при WM_ENDSESSION не закончиться, равно как и просто при WM_CLOSE главного окна. И сервису тоже. Тогда его будут убивать при shutdown — см. выше.
Re[3]: Когда же винда научится извлекать устройства?
Здравствуйте, Sinclair, Вы писали:

S>Ага, то есть когда я делаю ShutDown, то договориться можно, а когда Eject — то нет?

S>Вот от тебя, Павел, я такого не ожидал.

Зря не ожидал. Извини за большое цитирование. Все из Соломона-Руссиновича. Выделено мной

Остановка службы
Когда Winlogon вызывает Windows-функцию ExitWindowsEx, эта функция от-
правляет сообщение Csrss — процессу подсистемы Windows — для вызова
Csrss-процедуры завершения работы. Csrss осуществляет циклический перебор
активных процессов и уведомляет их, что система завершает работу. Для каж-
дого системного процесса, за исключением SCM, Csrss ждет несколько секунд,
количество которых определено параметром HKU\.DEFAULT\Control PanelDesktop\WaitToKillAppTimeout (по умолчанию 20 с), пока не будет осуществлен
выход из процесса, после чего переходит к следующему процессу. Когда Csrss
встречает процесс SCM, он также уведомляет его о завершении работы системы,
но использует лимит времени, определенный для SCM. Csrss распознает SCM,
используя идентификатор процесса, который Csrss сохранил при регистрации
SCM с Csrss с помощью функции RegisterServicesProcess в ходе инициализа-
ции системы. Лимит времени для SCM отличается от лимита других процессов,
поскольку Csrss знает, что SCM обменивается данными со службами, которым
при остановке нужно осуществить подчистку после своей работы. Поэтому ад-
министратору может понадобиться настроить только лимит времени, выделяе-
мый SCM. Параметр лимита времени SCM находится в разделе реестра HKLMSYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout и по умолчанию
составляет 12 секунд.
Обработчик остановки SCM отвечает за рассылку уведомлений всем службам,
запросившим уведомление об остановке при своей инициализации с помощью
SCM. SCM-функция ScShutdownAllServices осуществляет циклический перебор
записей служб в базе данных SCM в поиске служб, желающих получить уведомле-
ние об остановке, и отправляет каждой из них команду на остановку. Для каждой
службы, которой отправляется команда на остановку, SCM записывает параметр,
указывающий время ожидания службы, значение которого служба также определяет
при своей регистрации с помощью SCM. SCM отслеживает самое продолжительное
указанное время ожидания. После отправки сообщений об остановке SCM ждет,
либо пока одна из служб, которая была оповещена об остановке, не осуществит
выход, либо пока не пройдет самое продолжительное указанное время.
Если указанное время истечет, а служба не осуществит выход, SCM определя-
ет, не отправила ли одна или несколько служб, от которых ожидался выход, со-
общение SCM о том, что эта служба находится в процессе своей остановки. Если
хотя бы одна служба продвинулась в этом процессе, SCM снова ждет истечения
установленного времени ожидания. SCM продолжает выполнение этого цикла
ожидания, пока либо все службы не осуществят выход, либо ни одна из служб,
в отношении которых осуществляется ожидание, не уведомит его о нахождении
в процессе свой остановки за тот период времени, который указан для ожидания.
Пока SCM занимается отправкой приказов службам на остановку и ожида-
нием их выхода, Csrss ждет выхода от SCM. Если ожидание, осуществляемое
Csrss, заканчивается до того, как будет осуществлен выход SCM (по истечении
времени, указанного в параметре WaitToKillServiceTimeout), Csrss принудительно
завершает работу SCM и продолжает процесс завершения работы системы. Таким
образом, службы, давшие сбой при остановке за отведенное для этого время,
останавливаются принудительно. Такая логика позволяет системе завершать
работу вопреки тем службам, которые никогда не остановятся в результате де-
фектов своей конструкции
, но это также означает, что службы, требующие более
20 секунд, не завершат своих действий по остановке.
Кроме того, поскольку порядок остановки ничем не обусловлен, службы,
которые могут зависеть от других служб, для своей первоочередной остановки
не имеют способа сообщить об этом SCM, могут не иметь никаких шансов на
подчистку после своей работы.
В связи с этими потребностями в Windows реализуются предостановочные
уведомления и порядок остановки для противодействия проблемам, вызывае-
мым этими двумя сценариями. Предостановочные уведомления рассылаются
с использованием того же механизма, который используется для уведомлений
об остановке. Уведомления рассылаются тем службам, которые запросили предостановочные
уведомления посредством API-функции SetServiceStatus, и SCM
будет ждать от них подтверждения.
Идея, заложенная в этих уведомлениях, заключается в пометке тех служб,
у которых на подчистку может уйти много времени (это, к примеру, может
касаться служб сервера базы данных), и в выделении им большего количества
времени на завершение их работы. SCM отправит запрос на выяснение хода про-
цесса и будет 3 минуты ждать завершения работы тех служб, которые на него
ответили. Если служба за это время не ответит, она будет принудительно оста-
новлена в рамках процедуры завершения работы системы; в противном случае
она может продолжать свое выполнение столько времени, сколько потребуется,
пока она будет продолжать отвечать на запросы SCM.
Службы, участвующие в предварительной остановке (preshutdown), могут
также определить порядок остановки по отношению к другим службам, также
участвующим в предварительной остановке. Службы, зависящие от первооче-
редной остановки других служб (например, Group Policy должна дождаться
завершения работы службы обновления Windows Update), могут указать свои
зависимости от остановок других служб в параметре реестра HKLM\SYSTEMCurrentControlSet\Control\PreshutdownOrder.


Так что здесь намного сложнее. Если коротко — Windows при определенных условиях убивает сервисы при shutdown. Там это можно, все равно помирать. А тут нельзя. Иначе может рухнуть все зависимое от этого сервиса. Только с его согласия. А это есть — SERVICE_CONTROL_STOP


PD>>Вот, к примеру, сделаю я программу, которая делает fopen, а потом этот хендл не закрывает. Сидит в памяти, чем-то занимается, процессор загружает в среднем на 0%, а хендл не закрывает.

PD>>Как ее попросить ? Никак.
S>Повторюсь: несколько похожих задач были успешно решены примерно во времена Win7.

Ну не знаю, что именно было решено. Механизм этот ЕМНИП не менялся.

S>В частности, при шатдауне винда прекрасно строит список "несогласных", показывает их мне, и даже даёт выбор между "дать шанс закончиться добровольно" и "пристрелить к такой-то матери".


Обычных программ, добавь. А не сервисов.

S>В частности, при гибернейте твоя программа прекрасно "отпустит" диск, так что его можно будет извлечь с нулевым риском для его файловой системы.

S>Ну, только после пробуждения твоя программа словит ошибку обращения к диску — но это уже будет проблема этой программы (или пользователя, если он реально хотел, чтобы она всё-таки файл сохранила).

Так и сейчас совсем не обязательно, что если ты выдернешь флешку, с ее ФС будут проблемы. Ну не пишет, допустим, моя программа туда сейчас.
А при Hibernate все программы остановлены, так что точно не пишет. Ну а потом...

PD>>Windows не имеет права прибивать хендлы процесссов. Это имеет право делать только пользователь, берущий тем самым на себя ответственность за последствия.

S>Ну так дайте такую возможность пользователю. Что за детский сад?
PD>>Программ таких, принудительно закрывающих хендлы файлов, немало
S>Если бы они нормально работали...

Да в общем, работают. Использовал не раз.

PD>>https://udalenie-fajlov.softok.info/


PD>>Ну и сюда посмотри


PD>>https://serverfault.com/questions/1966/how-do-you-find-what-process-is-holding-a-file-open-in-windows

S>Смотрел. Почему не сделать это штатной фичей винды?

Потому что рискованно. Эти программы ты запускаешь на свой страх и риск, и MS ни за что не отвечает, если ты их используешь. А дай такую штатную возможность — закроет юзер все хендлы твоего любимого MS SQL именно в то время, когда он там что-то перестраивает, а потом начнутся вопли — где моя БД ?

PD>>Сделаю я из нее сервис, а то, о чем написал, так и оставлю.

S>Даже если не делать сервис — как думаешь, в какой версии винды появилось сообщение WM_QUERYENDSESSION?

Точно не знаю, но в 3.0 уже было.
Да, это запрос на согласие закончиться при окончании сессии.

Для сервисов аналоги — SERVICE_ACCEPT_STOP (можно остановить) и SERVICE_ACCEPT_SHUTDOWN (получает уведомление при завершении работы системы).


Но никто не мешает программе потом при WM_ENDSESSION не закончиться, равно как и просто при WM_CLOSE главного окна. И сервису тоже. Тогда его будут убивать при shutdown — см. выше.