Pull to refresh

Comments 28

Краткое изложение: «Ты жив пока о тебе помнят».
О мёртвых или хорошо (64 бит) или ничего. :)
Вряд ли. Согласно MSDN к моменту установки ExitCode и признака «мёртв» останавливаются все потоки, закрываются все хэдлы, выгружается исполняемый код. Значит сам процесс переводится в состояние «остановлен», а в этом состоянии CreateRemoteThread не работает. А поскольку своих потоков (а может и адресного пространства) у процесса нет, то запускать уже нечего.

Нет, оживлять некого, в зомби находятся только незакрытые, на момент завершения, handle. Ну и соответственно все reference (включая id и псевдо-закрытый handle процесса).


Кстати тот еще гиморой с этим, если это например listening socket, который резервируется за системой (и соединение на другом конце считается открытым), пока система не схлопнет, если ничего не предпринять (например переодически слать NOP пакет через такое соединение).
Такие сокеты называют псевдо-открытые или псевдо-закрытые (half-open (dropped),
half-closed)…
Даже если процесс перезапустится, то "netstat /abn" покажет 2-а listener на этом порту (один за системой, второй за новым процессом).


Кстати это происходит только если создавать дочерний процесс с флагом bInheritHandle=true (т.е. все дочерние handle наследуются родителем). Подробнее про процесс мучений можно почитать, например, тут Re: Fix windows issue with multiple workers, где я прививал nginx multi-processing под виндовс...

Даже страшно спросить, как именно вы на это наткнулись. Для чего вообще может понадобиться вызов такой функции (кроме системных мониторов типа ProcessExplorer)?
Для чего вообще может понадобиться вызов такой функции (кроме системных мониторов типа ProcessExplorer)?

Например, для инъекции кода, когда хотим подгрузить свою библиотечку в чужой процесс.
Между GetExitCodeProcess() и IsWow64Process() всё равно будет рейс.
Даже в случае если GetExitCodeProcess() вызывать после IsWow64Process()?
Ну да. Не поверите правильному IsWow. Если только вам мертвые совсем не нужны…
Ну, если нам нужны данные по живому процессу, то:

GetExitCodeProcess()
IsWow64Process()
GetExitCodeProcess()

Если оба вызова GetExitCodeProcess() вернули STILL_ACTIVE — то результату IsWow64Process() можно верить.
Так — да, я буквально текст понял просто.
С чего бы можно верить?
сразу после первого GetExit грохаем процесс, а перед вторым стартуем другой процесс с таким же PID.
Не поведаете, как зареюзать PID процесса?
Алсо, работа идет с открытым хэндлом процесса, а не с его ID
Когда-то давно пытался с помощью этой функции определять разрядность винды, на которой запускается программа Долго не мог понять почему не всегда правильно определяет, пока не дочитал до конца описание и очень огорчился. Настолько, что переехал с плюсов на шарп для десктоп приожений.
В шарпе можно не дочитывать до конца описание WinAPI функций по причине пониженных требований к стабильности софта, написанного на шарпе или стараетесь не вылезать за пределы возможностей самого фреймворка? Никакого сарказма, реально пытаюсь пытаюсь понять мотивацию.
Стояла простая задачка — при запуске программы определять разрядность ОСи, в зависимости от этого делать то или иное действие. Я тогда был совсем джуном, можно было самому выбирать язык и среду, решил делать на QT, нативного способа не нашёл, обратился к WinApi и этой функции. Импортировал, проверил, реализовал функционал и интерфейс. При эксплуатации начались жалобы, что неверно определяет разрядность. Внимательно прочитал MSDN. Дошёл до места:
A pointer to a value that is set to TRUE if the process is running under WOW64. If the process is running under 32-bit Windows, the value is set to FALSE. If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE.

Огорчился. Начал искать способ определения разрядности ВООБЩЕ. Нашёл Environment.Is64BitOperatingSystem в шарпе. Переписал на нём программку. Ну и пошло-поехало.
Так а что не так с этим местом в MSDN? Если Ваша программа скомпилирована 64-битной и она сейчас работает — значит ОС определённо 64-битная. Если Ваша программа скомпилирована 32-битной, то смотрим на результат: если он FALSE — то мы под 32-битной ОС, если он TRUE — то под 64-битной. Плюс отдельно случай когда мы на очень старой винде, где IsWoW64Process() вообще нет в kernel32.dll — эта винда определённо 32-битная.

Описання в статье проблема не может возникнуть при работе с хендлом своего приложения — мы не можем быть «зомби» если наш код ещё выполняется.
Я же говорю — было дело очень давно и от функции ожидался простой ответ «да 64» или «Нет 32». Программа была настолько простой, что мне на тот момент оказалось проще написать на шарпе, чем понять смысл работы этой функции.
Функция GetExitCodeProcess так же имеет некоторые ограничения, описанные в секции Important. Так что если процесс уже вот-вот станет «зомби», а поток еще не завершен, то подход GetExitCodeProcess() + IsWow64Process() тоже может не сработать.
Заметка интересная и хорошо что вы её написали. Это полезно.
Но простите, вроде логично что сначала стоит проверить есть ли в системе такой процесс и жив ли он.
А уже потом пытаться понять — x64 он или нет.
Мне вначале подумалось, что IsWow64Process() делает эту проверку внутри и быстрый тест (с невалидным PID) это предположение вроде бы подтвердил. Ошибка обнаружилась лишь значительно позже, при попытке взаимодействовать с «зомби». Теперь, конечно, проверяю.
Подозреваю что там просто проверка на существование процесса, а вот на то что «пациент скорее мёртв чем жив» или «пациент скорее жив чем мёртв» никто не смотрит.
Все верно: никто не обещал, что функция IsWOW отработает корректно для процесса-зомби. 32 битная подсистема у него выгружена, там нет ни кода, ни потоков 32 битных — с чего ему определиться как x86?
Если функция в некоторых обстоятельствах выдаёт неверный (или неопределённый) результат — то об этом следует писать в документации. В MSDN данный случай не описан — об этом и статья.
А здесь нет неверного результата. Это все равно как если вы запросите размер файла, который будет удален в то время, как система возвращается из системного вызова, наподобие NtQuerySystemInformation или через что там проходит определение размера. И получив размер в мегабайт, вы будете недовольны: как так, файл же удален, почему мне не выкинули C000000F…
Sign up to leave a comment.