Что бы вы там себе не думали, а зомби существуют. И они действительно едят мозги. Не человеческие, правда, а компьютерные. Я говорю сейчас о зомби-процессах и потребляемых ими ресурсах. Это будет душераздирающая история о потерянных и снова найденных 32 ГБ оперативной памяти. Возможно, лишь некоторые из вас столкнутся с точно такой же проблемой, но если вдруг это произойдёт — у вас хотя бы будет шанс понять, что происходит.

Начнём с того, что компьютеры под управлением ОС Windows склонны со временем терять память. Ну, по крайней мере, у меня, при моём способе ими пользоваться. После пары недель без перезагрузок (или, например, всего одного уикэнда за который я 300 раз пересобрал Хром) я стал замечать, что диспетчер задач начинает показывать мне очень маленькое количество свободной оперативной памяти, но в то же время в системе нет никаких процессов, которые эту самую память активно используют. В том примере выше (с 300 сборками Хрома) диспетчер задач сказал мне, что в системе занято 49.8 ГБ плюс ещё 4.4 ГБ памяти сжато — но при этом запущено всего несколько процессов, и все они в сумме даже и близко не используют столько памяти:

image

В моём компьютере 96 ГБ оперативной памяти (да, я счастливчик) и когда у меня нет вообще никаких запущенных процессов — я, знаете ли, хотел бы видеть ну хотя бы половину этой памяти свободной. Я правда рассчитываю на это. Но иногда этого достичь не удаётся и мне приходится перезагружать ОС. Ядро Windows написано качественно и надёжно (без шуток), так что память не должна бы пропадать бесследно. Но всё же она пропадает.

Первой же моей догадкой стало воспоминание о том, что один из моих коллег как-то жаловался на зомби-процессы, которые иногда остаются в ОС уже не активными, но всё же ещё не до конца удалёнными ядром. Он даже написал специальную утилиту, которая выводит список таких процессов — их имена и количество. Когда он запускал эту утилиту в своих тестах, то получал до нескольких сотен зомби-процессов на обычной Windows-машине. Я нашел его инструмент, запустил на своём компьютере и получил… 506 000 зомби-процессов. Да, 506 тысяч!

Я вспомнил, что одной из возможных причин перехода процесса в состояние «зомби» может быть то, что какой-то другой процесс держит открытым его дескриптор (handle). В моём случае большое количество зомби-процессов играло мне на руку — им было сложнее скрыться. Я просто открыл диспетчер задач и добавил на вкладку Details столбец с количеством открытых дескрипторов для каждого процесса. Затем отсортировал список по убыванию значений в этом столбце. Я сразу нашел героя данной истории — процесс CcmExec.exe (часть Microsoft System Management Server) имел 508 000 открытых дескрипторов. Это было во-первых, очень много, а во-вторых, подозрительно близко к найдненному мною выше числу в 506 000 зомби-процессов.

image

Я убил процесс CcmExec.exe и получил следующий результат:

image

Всё получилось ровно так, как я того и ожидал. Как я без иронии писал выше — ядро Windows написано очень хорошо и когда процесс уничтожается, то и все занятые им ресурсы освобождаются. Закрытие CcmExec.exe освободило 508 000 дескрипторов, что дало возможность окончательно закрыть 506 000 зомби-процессов. Количество свободной оперативной памяти мгновенно выросло на 32 ГБ. Тайна раскрыта!

Что такое зомби-процесс?


До этого момента мы ещё не выяснили, что же заставило все эти процессы зависнуть в неопределённости, а не быть удалёнными. Похоже на то, что мы имеем дело с тривиальным багом в приложении (а не в ядре ОС). Общее правило гласит, что когда вы создаёте процесс, то получаете его дескриптор и дескриптор его главного потока. Вы ОБЯЗАНЫ закрыть эти дескрипторы. Если вашей задачей было просто запустить процесс — их можно закрыть сразу же (это не убъёт запущенный процесс, а просто разорвёт связь вашего процесса с ним). Если новый процесс вам для чего-то нужен (например, вы ждёте окончания его работы или вам нужен код, который он вернёт) — то нужно воспользоваться соответствующими функциями (например, WaitForSingleObject(hProcess, INFINITE) для ожидания выхода или GetExitCodeProcess(hProcess, &exitCode) для получения кода возврата) и всё-равно закрыть дескрипторы после того, как вы получили от дочернего процесса всё, чего хотели. Аналогично следует и поступать и с дескрипторами процессов, которые вы для чего-нибудь открываете с помощью функции OpenProcess().

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

Куда же девается память?


Ещё одним инструментом, который я использовал в своём исследовании, была утилита RamMap. Она показывает использование каждой страницы памяти. На вкладке Process Memory мы видим сотни тысяч процессов, каждый из которых занимает 32 КБ оперативной памяти — очевидно, это и есть наши зомби. Но ~500 000 раз по 32 КБ будет равно примерно 16 ГБ — куда же делась остальная память? Сравнение состояния памяти до и после закрытия зомби-процессов даёт ответ на этот вопрос:

image

Мы можем чётко увидеть, что ~16 ГБ уходит на Process Private Memory. Также мы видит, что ещё 16 ГБ приходится на Page Table Memory. Очевидно, что каждый зомби-процесс занимает 32 КБ в таблице страниц памяти и еще 32 КБ использует для своей личной памяти. Я не знаю для чего зомби-процессу так много памяти, но, наверное, никто никогда не думал, что число таких процессов может измеряться сотнями тысяч.

Некоторые типы занятой памяти увеличились после закрытия процесса CcmExec.exe, в основном это касается Mapped File и Metafile. Я не знаю точно, почему так получилось. Одной из моих догадок является то, что ОС решила, что свободной памяти теперь достаточно и что-то себе закешировала. Это, в общем, не плохо. Мне не жаль памяти для нужд ОС, я просто не хочу, чтобы она пропадала совсем уж бесцельно.

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

Я написал твит о моей находке и исследование продолжил другой программист, который сумел воспроизвести данный баг и передать информацию о нём разработчику из Microsoft, который сказал, что это «известная проблема, которая иногда случается, когда очень много процессов запускаются и закрываются очень быстро».

Я надеюсь, что данная проблема будет скоро исправлена.

Почему у меня на компьютере возникают такие странные проблемы?


Я работаю над кодом Windows-версии Хрома и одной из моих задач является оптимизация его сборки на этой ОС, а это требует многократных запусков этой самой сборки. Каждая сборка Хрома запускает огромное множество процессов — от 28 000 до 37 000 в зависимости от выбранных настроек. При использовании нашей распределённой системы сборки (goma) эти процессы создаются и закрываются очень быстро. Мой лучший результат сборки Хрома — 200 секунд. Но столь агрессивная политика запуска процессов выявляет и проблемы в ядре Windows и её компонентах:

  • Быстрое удаление процессов ведёт к зависаниям пользовательского ввода
  • Драйвер тачпада выделяет, но не освобождает память при каждом создании процесса
  • App Verifier создаёт O(n^2) лог-файлов (и об этом стоит написать отдельный пост!)
  • Есть баг в ядре Windows, который касается буферизации файлов, и этот баг воспроизводится на всех Windows от Server 2008 R2 до Windows 10
  • Windows Defender задерживает запуск каждого процесса goma на 250 мс

Что дальше?


Если вы работаете не на компьютере, управляемом политиками компании, то процесс CmmExec.exe у вас не запущен и с конкретно данным багом вы не столкнётесь. Также он коснётся вас только если вы собираете Хром или делаете ещё что-то похожее, создавая и закрывая при этом десятки тысяч процессов в короткие промежутки времени.

Но!

CcmExec — не единственная в мире программа с багами. Я нашел много других, содержащих в себе конкретно этот же тип ошибок, приводящих к созданию зомби-процессов. И есть ещё огромное множество тех, которые я не нашел.

Как знают все опытные программисты, любая ошибка, которая не была явно исправлена или предупреждена — точно когда-то произойдёт. Просто написать в документации «Пожалуйста, закройте этот дескриптор» — не достаточно. Так что вот мой вклад в то, чтобы сделать нахождение подобного типа ошибок проще, а их исправление — реальнее. FindZombieHandles — это инструмент, основанный на NtApiDotNet и коде от @tiraniddo, который выводит список зомби-процессов и информацию о том, кто сделал их зомби. Вот пример вывода данной утилиты, запущенной на моём компьютере:

274 total zombie processes.
249 zombies held by IntelCpHeciSvc.exe(9428)
249 zombies of Video.UI.exe
14 zombies held by RuntimeBroker.exe(10784)
11 zombies of MicrosoftEdgeCP.exe
3 zombies of MicrosoftEdge.exe
8 zombies held by svchost.exe(8012)
4 zombies of ServiceHub.IdentityHost.exe
2 zombies of cmd.exe
2 zombies of vs_installerservice.exe
3 zombies held by explorer.exe(7908)
3 zombies of MicrosoftEdge.exe
1 zombie held by devenv.exe(24284)
1 zombie of MSBuild.exe
1 zombie held by SynTPEnh.exe(10220)
1 zombie of SynTPEnh.exe
1 zombie held by tphkload.exe(5068)
1 zombie of tpnumlkd.exe
1 zombie held by svchost.exe(1872)
1 zombie of userinit.exe

274 зомби — это ещё не так плохо. Но уже и это указывает на определённые проблемы, которые могут быть найденны и исправлены. Процесс IntelCpHeciSvc.exe в этом списке имеет самые большие проблемы — похоже на то, что он открывает (и забывает закрыть) дескриптор процесса каждый раз, когда я открываю видео в Windows Explorer.

Visual Studio забывает закрыть дескрипторы как минимум двух процессов, в одном случае это воспроизводится всегда. Просто запустите сборку проекта и подождите ~15 минут пока процесс MSBuild.exe закроется. Можно также выставить опцию “set MSBUILDDISABLENODEREUSE=1” и тогда MSBuild.exe закроется сразу по окончанию сборки и потерянный дескриптор будет виден сразу. К сожалению, какой-то негодяй в Microsoft исправил эту проблему и фикс должен выйти в обновлении VS 15.6, так что поторопитесь воспроизвести её, пока это ещё работает (надеюсь, не нужно объяснять, что это была шутка и никакой он на самом деле не негодяй).

Также вы можете использовать для просмотра забытых процессов программу Process Explorer, сконфигурировав её нижнюю панель так, как это показано ниже (заметьте, что в этом случае будут показаны забытые дескрипторы как для процессов, так и для потоков):

image

Вот пару примеров найденных багов (о некоторых сообщено разработчикам, но не о всех):

  • Утечка в CcmExec.exe (описанный выше случай с 500 000 зомби) — разработчики работают над исправлением
  • Утечка в Program Compatibility Assistant Service — проблема исследуется
  • Утечка в devenv.exe + MSBuild.exe (проблема уже исправлена)
  • Утечка в devenv.exe + ServiceHub.Host.Node.x86.exe (багрепорт отправлен)
  • Утечка в IntelCpHeciSvc.exe + Video.UI.exe для каждого открытого видеофайла (Intel приняла багрепорт и переслала его в Lenovo)
  • Утечка в RuntimeBroker.exe + MicrosoftEdge и Video.UI.exe (возможно, имеет отношение к некоторым другим багам в RuntimeBroker.exe)
  • Утечка в AudioSrv + Video.UI.exe
  • Утечка в одном внутреннем инструменте Google из-за использования старой версии psutil
  • Утечка в утилитах от Lenovo: tphkload.exe теряет один дескриптор, SUService.exe теряет три
  • Утечка в Synaptic’s SynTPEnh.exe

Дескрипторы процессов — не единственный тип ресурсов, который может утекать таким образом. Например, “Intel® Online Connect Access service” (IntelTechnologyAccessService.exe) использует всего 4 МБ оперативной памяти, но, будучи запущенной 30 дней, создаёт 27 504 дескрипторов. Эту проблему можно обнаружить с помощью Диспетчера Задач, я отправил разработчикам багрепорт о ней:

image

Используя Process Explorer, я заметил, что NVDisplay.Container.exe открывает ~5000 дескрипторов на событие \BaseNamedObjects\NvXDSyncStop-61F8EBFF-D414-46A7-90AE-98DD58E4BC99, создавая новый дескриптор каждые две минуты. Я так понимаю, они хотят быть супер-уверены в том, что могут остановить NvXDSync? Багрепорт Nvidia отправлен.

image

Corsair Link Service создаёт ~15 дескрипторов в секунду, не освобождает их совсем. Багрепорт отправлен.

Adobe’s Creative Cloud теряет тысячи дескрипторов (около 6500 в день, по моим подсчётам). Багрепорт отправлен.

Razer Chroma SDK Service теряет ОЧЕНЬ много дескрипторов (150 000 в час?). Багрепорт отправлен.

Удивительно, что никто до этого особо не обращал внимание на подобные баги. Эй, Microsoft, возможно, стоит собирать статистику по таким случаям и что-то предпринимать по этому поводу? Эй, Intel и Nvidia, почистите немного ваш код. Помните, я наблюдаю за вами.

А теперь вы можете взять утилиту FindZombieHandles, запустить её на вашей машине и рассказать о своих находках. Также вы можете использовать в экспериментах диспетчер задач и Process Explorer.

Комментарии (76)


  1. TrllServ
    26.02.2018 11:45

    0 total zombie processes.
    No zombies found. Maybe all software is working correctly...

    Меня несколько лет назад, тоже интересовала эта тема, думая вам стоит ознакомиться с superfech. В реальности она будет кушать ровно столько памяти, сколько доступно. Проверял на машинках с 4, 16 и 32 Гб памяти, ОС Win7 и 8.1.
    В некоторых случаях, её есть смысл отключать, работает не так как хотелось бы. Например на тех же компиляциях при наличии ссд.


  1. reversecode
    26.02.2018 11:57

    RamMap не запустился, у вас недостаточно памяти для запуска приложения ЛОЛ
    при этом тот же текучий хром запущен успешно поедает память


  1. MonkAlex
    26.02.2018 12:35

    0 total zombie processes.
    No zombies found. Maybe all software is working correctly, but I doubt it. More likely the zombie counting process failed for some reason. Please try again.


  1. Revertis
    26.02.2018 13:31

    1731 total zombie processes.
    Количество постепенно растёт. Браузер закрыт. Win10, x64.
    Пока писал этот коммент 5 зомбей прибавилось.


  1. keydon2
    26.02.2018 13:32

    Это кошмар, ребятки.
    Колоссальные усилия для поиска зомби. Ваш коллега написал утилиту, вы в ручную ставили множество других программ и нетривиально находили эти процессы.
    В процессе нашли несколько багов в самой винде, так еще и утечку в более чем 10 популярных приложений.
    Что-то в этом виндовс-мирке точно не так.


    1. alexoron
      26.02.2018 15:56

      Что-то в этом виндовс-мирке точно не так.

      Если что в юниксовых системах тоже существуют процессы-зомби.
      Выходит, в юникс-мирке что-то не так тоже?


      1. lorc
        26.02.2018 16:47

        Они существуют. Но их показывает ps и поэтому очень непросто заметить приложение, которое их плодит. У на машине сейчас только pidgin таким страдает.


        1. khim
          26.02.2018 17:41

          К сожалению Unix-мир зря гордится. Зомби в Unix-мире заметны сразу, так что 500'000 штук никто не оставит.

          Но вот всякое добро внутри X сервера, оставленное там «умершими» программами или ошмётки от криво реализованного IPC (который не освобождает ресурсы, если программа забывает это делать) — приводят примерно к такому же эффекту.

          Увы, но нет в мире операционок без подобных эффектов. Android к этому стремится (в частности поэтому он не поддерживает POSIX IPC), но… он тоже идеала пока не достиг…

          P.S. Причём заметим, что в случае с POSIX IPC всё хуже — реализовно оно в ядре и API там такой, что избавиться от утечек в принципе нельзя. По крайней мере разработчики Windows могут гордится тем, что ядро «не теряет» память…


          1. splav_asv
            26.02.2018 23:40

            Справедливости ряди, это скорее к Sytem V IPC относится. В POSIX чуть лучше — объекты освобождаются как только больше не нужны ни одному процессу.

            А так ещё открытые, удалённые с диска, файлы можно припомнить. Тоже в своём роде утечка места.


    1. Dywar
      26.02.2018 20:42

      Оставлю тут — www.cvedetails.com/top-50-products.php?year=2016
      С годами ТОП меняется, но Linux там явно не среди последних.


  1. acmnu
    26.02.2018 14:29

    Странно, что так необходимо подтверждение от родительского процесса. Итересно зачем это сделано именно так. Насколько я понимаю аналогичный api в unix, то там нет блока: умер процесс, родителя об этом уведомили, а если он не среагировал, это его проблемы.


    1. lieff
      26.02.2018 15:05

      Не совсем. Нужно выполнить waitpid(childPid, &returnStatus, 0); в обработчике SIGCHILD или без него. Иначе получим такого-же зомби. Тут скорее фактор, что зомби сразу же видны в top, потому таких ошибок меньше.


    1. khim
      26.02.2018 17:42

      Насколько я понимаю аналогичный api в unix, то там нет блока: умер процесс, родителя об этом уведомили, а если он не среагировал, это его проблемы.
      Будет зомби — точно так же, как в Windows. Просто эти зомби будут в списке процессов видны, это заметят и будут чинить.

      Разница не в подходе, а в средствах диагностики…


      1. acmnu
        26.02.2018 17:47

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


        1. sumanai
          26.02.2018 17:51

          Нельзя просто так взять и отнять дескриптор у процесса, точнее, можно, но процессу это может не понравится. Может он действительно нужен для каких-то своих целей, даже после закрытия?


        1. khim
          26.02.2018 19:01
          +3

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

          От зомби нужно, по большому счёту, две вещи:
          1. Запомнить код возврата (чтобы родитель смог понять — отработал процесс-потомок успешно или нет).
          2. Слот в таблице процессов (так как если этого не сделать, то, опять-таки, невозможно будет говорить о коде возврата процесса с заданным PID'ом… их ведь может быть много, если в системе нет понятия «зомби»).

          Так как обычно зомби долго не живут, то оставить для них один несколько больше информации — не очень страшно, но очень сильно помогает для «посмертного анализа» (если зомби вовремя не умирают, то возможность понять — что это за процессы и как они были запущены — очень полезна).


      1. alexxz
        26.02.2018 19:41

        Всё ж в Linux зомби чуть более мирные. Остаётся только лишняя запись в таблице процессов. Бывшая память зомби процесса уже свободна.
        Правда в результате может быть переполнение таблицы процессов… Так что увы.


        1. khim
          26.02.2018 20:47

          Всё ж в Linux зомби чуть более мирные. Остаётся только лишняя запись в таблице процессов.
          Не только. Вроде бы ещё в ядре какое-то количество структур остаётся. 8K, если память не изменяет. Что, конечно, в 4 раза меньше, чем в Windows… но всё равно довольно много.


  1. emreu
    26.02.2018 16:26

    Теперь понятно почему хром такой прожорливый. Вот если бы у его разработчиков было не по 50 гигов, а 8 или даже 4, то они бы чаще обращали внимание на проблемы с памятью. А то запустил пару-тройку приложений на электроне + сам хром и уже 6-7 гигов как не бывало!


    1. sumanai
      26.02.2018 16:28

      Им память нужна для сборки, иначе компилировать они его будут месяц.


      1. emreu
        26.02.2018 17:02

        Это понятно. Просто когда постоянно живёшь в достатке ресурсов, то проблемы «третьего мира» начинают казаться несущественными. Подозреваю что сборки тестируются в том числе на ограниченных конфигурациях, но вряд ли основная масса разаработчиков постоянно живёт в таких условиях. Из-за этого может формироваться мнение, что раз нормально работает у меня локально, то и у всех будет так же.


        1. PsyHaSTe
          27.02.2018 16:56

          Такое количество памяти требуется для разработки, а не для тестирования.

          Например у меня на машине 8 гигов, и если я при загрузке винды запущу любое приложение, например браузер с двумя вкладками, то докеру не хватит памяти и он не сможет запуститься. То есть в моем случае 16 гигов — это МИНИМУМ, без которого всему необходимому мне для разработке софту не хватит места для запуска.

          Так что это физически невозможно, да и не нужно.


        1. TrllServ
          27.02.2018 17:21

          Если б они полноценно тестировались на «ограниченных конфигурациях», вряд ли браузеры подлагивали на i3 и тормозили на atom'ах.


      1. khim
        26.02.2018 17:43

        Компилировать — нет, для этого много памяти не нужно. А вот линкер при сборке Хрома может десятки гигабайт в одиночку выжирать…


      1. quwy
        27.02.2018 02:45

        На виртуалке с 8 ГБ и обычным HDD у меня собирается где-то пол часа.


    1. F0iL
      26.02.2018 21:43
      +1

      то они бы чаще обращали внимание на проблемы с памятью.

      Они обращают, и очень активно. В Chromium есть специальная Memory Team, состоящая из инженеров Google и Opera, которая занимается выяснениями «на что тратится память» (в столь большом и сложном проекте подобный вопрос тянет не на одно исследование) и оптимизациями всего этого дела. Результаты у них может и не впечатляющие, но значительные.
      Плюс от разработчиков V8 периодически тоже приходят новости об успехах по этой части.
      и уже 6-7 гигов как не бывало

      Это нормально. Точнее сказать, так и должно быть. У Chromium сознательная политика вида «если есть память, нужно ее использовать под кэши/буферы/другие в определенной степени полезные вещи». Внутри браузере есть механизм определения так называемого 'memory pressure', и когда памяти в системе становится маловато (уровень 'moderate') или совсем мало (уровень 'critical'), компонентам браузера рассылается уведомление, что не мешало бы почиститься и ужаться.
      Обычный пользователь может прикоснуться и даже немного повлиять на эту магию с помощью опций, начинающихся с --memory-pressure* в командной строке, поглядите, там разные параметры есть.
      Сейчас все это дело еще перепиливается, решения об оптимизации потребления ОЗУ во время выполнения и выгрузке различных данных будут применяться также исходя из пользовательской активности и других факторов, процесс еще не завершен, но вообще будет много интересного.


      1. Maccimo
        01.03.2018 18:30

        Может быть и обращают.
        Но по моим наблюдениям, когда памяти остаётся маловато или совсем мало, у хрома начинаются серьёзные проблемы.
        Начиная с задержек отрисовки табов в заголовке окна и заканчивая сообщениями «Вкладка не отвечает» после попытки открыть новую пустую (!) вкладку.


        1. khim
          01.03.2018 19:36

          Новая пустая вкладка вообще-то запускает целый новый процесс — со всеми вытекающими.


    1. Daniil1979
      28.02.2018 11:15
      -1

      А Вы ещё пользуетесь хромом??? Я его поставил себе, использовал несколько дней, заметил, что комп стал работать сильно медленнее, открыл диспетчер задач, увидел, что большую часть памяти и процессора жрёт именно хром. Снёс хром — с тех пор комп просто летает.


  1. sumanai
    26.02.2018 16:27

    А теперь вы можете взять утилиту FindZombieHandles, запустить её на вашей машине и рассказать о своих находках.

    Требует .NETFramework 4.5, увы. Впрочем, на моей XP x64 редко у какого процесса есть больше 1000 дескрипторов, и зомби процессов и памяти я там не наблюдаю.


    1. TrllServ
      26.02.2018 16:38

      .нет 4.5 уже не ставится на ХР или это из-за мало совместимого х64 у ХР?


      1. sumanai
        26.02.2018 16:53

        Первое.


    1. mayorovp
      27.02.2018 08:46

      Попробуйте пересобрать под более старый .NET. Там же ничего кроме P/Invoke не используется… Еще можно попробовать под Mono запустить.


      1. sumanai
        27.02.2018 17:31

        Не, бесполезно. Там все проблемы в библиотеке NtApiDotNet, не знаю, как это им удаётся, но компилироваться под 4.0 она никак не хочет, хотя казалось бы, простой враппер для функций.
        Конфиг правил, не катит.


        1. mayorovp
          27.02.2018 18:42

          Там надо, видимо, асинхронные функции порезать. Или библиотеку с реализацией асинхронности подключить.

          А что говорит Mono?


          1. sumanai
            27.02.2018 19:35

            Там надо, видимо, асинхронные функции порезать. Или библиотеку с реализацией асинхронности подключить.

            Да, несостыковки вылазили как раз на async с await. А какие библиотеки есть?
            А что говорит Mono?

            Не знаю, с какой стороны к нему подступится, но на странице загрузки есть только Supported on Windows 7, 8, 10 or later. Сейчас посмотрю старые версии, но вряд ли что выйдет.


            1. mayorovp
              27.02.2018 19:37

              Тогда Microsoft.Bcl.Async


              1. sumanai
                27.02.2018 20:59

                Так, хорошо, уже запустилось, правда пришлось пару методов «зануллить». На десятке работает и показывает значения, равные оригиналу, но на XP ругается на отсутствие привилегии отладки и не может импортировать NtGetNextProcess из ntdll. Такая функция в XP должна быть, судя по WRK, но не экспортируется.
                Ладно, спасибо за помощь.


  1. FeNUMe
    26.02.2018 16:41

    4 total zombie processes.
        1 zombie held by Dropbox.exe(7120)
            1 zombie of chrome.exe
        1 zombie held by svchost.exe(1320)
            1 zombie of userinit.exe
    Pass -verbose to get full zombie names.

    Пожалуй помониторю пару дней. Уже не раз обращал внимание на «потери» памяти, грешил на возможные зловреды, но ни разу словить в AVZ/Gmer не удавалось. Может и правда дело в зомбях.


    1. khim
      26.02.2018 17:45

      Десяток зомбей сожруть меньше мегабайта памяти. Чтобы беда случилась их должны быть тысячи…


      1. FeNUMe
        26.02.2018 18:28

        Потому и говорю что помониторю, утром ОС ребуталась и уже 4 зомби, хотя я еще толком на компе ничего не делал.


        1. khim
          26.02.2018 19:03

          Как я писал выше: появление (и исчезновение) зомби — это нормально. Ненормально — это когда они «зависают» в «полумёртвом» состоянии на часы (а то и дни).


  1. jazzl0ver
    26.02.2018 18:07

    У меня вывод handle не совпадает с кол-вом открытых дескрипторов:
    image
    D:\Work>handle.exe -p 4268 | wc -l
    30

    Интересно, почему…
    Если что — это Windows 7. Также пробовал на Windows 10, там тоже на порядки отличается.


    1. MikailBag
      26.02.2018 19:52
      +1

      Так она же только зомби считает, а не все открытые хэндлы.


      1. jazzl0ver
        26.02.2018 20:01

        Она — это кто?


    1. mikhaelkh
      26.02.2018 20:54

      Nthandle v4.11 — Handle viewer
      Copyright © 1997-2017 Mark Russinovich
      Sysinternals — www.sysinternals.com

      usage: handle [[-a [-l]] [-u] | [-c [-y]] | [-s]] [-p |] [name] [-nobanner]
      -a Dump all handle information.
      -l Just show pagefile-backed section handles.
      -c Closes the specified handle (interpreted as a hexadecimal number).
      You must specify the process by its PID.
      WARNING: Closing handles can cause application or system instability.
      -y Don't prompt for close handle confirmation.
      -s Print count of each type of handle open.
      -u Show the owning user name when searching for handles.
      -p Dump handles belonging to process (partial name accepted).
      name Search for handles to objects with (fragment accepted).
      -nobanner Do not display the startup banner and copyright message.

      No arguments will dump all file references.

      Надо было
      handle -a -nobanner -p 4268 | wc -l

      или
      handle -s -nobanner -p 4268


      1. jazzl0ver
        26.02.2018 22:39

        Посыпал голову пеплом. Спасибо!


  1. vvzvlad
    26.02.2018 19:13

    А у меня вот Reeder запускает на каждый просмотр страницы внутри себя Safari, и похоже, забывает их правильно закрывать.

    В итоге, ест память больше хрома


  1. Alex023
    26.02.2018 22:52

    geektimes.ru/post/107605
    geektimes.ru/post/107607
    geektimes.ru/post/107637
    Это уже почтенного возраста статья конечно. Но как я вижу актуальности не теряет. Да и по сей день встречаются толпы людей из «тёмного царства», нуждающиеся в лучиках света.
    Поток людей, творящих чёрт знает что с памятью не уменьшается со временем.

    Последнее что видел буквально с месяц назад — как у клиентов вырубается виртуальная машина выполняющая роль терминала для 20 учетных записей. Ей отвели всего-навсего 384 Мб ОЗУ в VMWare (ОС WinServ2003). Один клиент съедает 804 Мб ОЗУ. Даже один клиент заставляет машину жить в жОстком свопе. Что происходит при подключении 20 клиентов… ну то что происходит, машина умирает. Хорошо когда люди включают голову, хотя бы иногда, при настройке софта и выборе нагрузок на железо!


  1. Shaltay
    26.02.2018 23:32
    -2

    Глубокое отвращение к продуктам Microsoft не позволяет мне тратить время на подобные расследования. Однако, могу отметить, в линуксе зомби мозги память не жрут, просто ходят и жалобно мычат.


    1. khim
      26.02.2018 23:46

      Жрут точно также, просто чуть меньше.



  1. mayorovp
    27.02.2018 08:54

    App Verifier создаёт O(n^2) лог-файлов (и об этом стоит написать отдельный пост!)

    Судя по твиту — он создает ровно n файлов. А вот времени на это тратит таки O(n^2)


  1. roboter
    27.02.2018 10:32

    ой, ой.
    WARNING: Can't enable debug privilege. Some zombies may not be found. Run as admin for full results.
    227 total zombie processes.
    185 zombies held by svchost(11768)
    93 zombies of chrome.exe
    17 zombies of ServiceHub.RoslynCodeAnalysisService32.exe
    15 zombies of ServiceHub.IdentityHost.exe
    14 zombies of Node.exe
    9 zombies of ServiceHub.Host.CLR.x86.exe
    8 zombies of ServiceHub.VSDetouredHost.exe
    8 zombies of ServiceHub.SettingsHost.exe
    6 zombies of ServiceHub.DataWarehouseHost.exe
    3 zombies of Microsoft.VsHub.Server.HttpHost.exe
    2 zombies of software_reporter_tool.exe
    2 zombies of software_reporter_tool.exe
    2 zombies of RdrCEF.exe
    2 zombies of phantomjs.exe
    2 zombies of conhost.exe
    1 zombie of Code.exe
    1 zombie of AcroRd32.exe
    22 zombies held by svchost(3696)
    22 zombies of RAVBg64.exe
    12 zombies held by IntelCpHeciSvc(7224)
    4 zombies of Video.UI.exe
    4 zombies of Video.UI.exe
    4 zombies of Video.UI.exe
    3 zombies held by devenv.exe(28936)
    2 zombies of ServiceHub.Host.Node.x86.exe
    1 zombie of MSBuild.exe
    1 zombie held by SynTPEnh.exe(27400)
    1 zombie of SynTPEnh.exe
    1 zombie held by sihost.exe(16604)
    1 zombie of backgroundTaskHost.exe
    1 zombie held by svchost(2232)
    1 zombie of userinit.exe
    Pass -verbose to get full zombie n

    P.S. chrome.exe даже не запускался.


  1. emusic
    27.02.2018 12:55
    -1

    Автор, безусловно, путает процессы и хэндлы. Будь у него 506 тысяч зависших процессов — большинство PID'ов давно стало бы шести-и семизначными.


    1. hdfan2
      27.02.2018 14:14

      В ссылке на твиттер (выше): «Also my PIDs are well into the 2,000,000 range.»


  1. questor
    27.02.2018 15:07

    Всего лишь 202 зомби, хотя не перегружался неделю и в студии постоянно открываю тяжеловесные проекты (хотя прямо говоря — да, приходится порой студию из процессов убивать, т.к. держит файлы)


  1. iCpu
    28.02.2018 06:44
    -1

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

    У меня, например, на 8.1 пусто после 8-часовой работы в Qt с периодическими инкриментальными сборками студией и мингвой.


  1. Skerrigan
    28.02.2018 08:30

    Простите далекого от этого, но вот я с гита слил репу, нахожусь в директории с «программой», но что с этим делать дальше? Можно на пальцах? Как это вообще запускается?


    1. mayorovp
      28.02.2018 09:22

      Зайдите в папку prebuilt — там бинарники лежат.

      А вообще, для сборки проекта надо поставить Microsoft Build Tools 2017, после чего запустить из командной строки msbuild находясь в папке проекта — он соберет.


      1. Skerrigan
        28.02.2018 09:38

        Все, теперь понял.
        *Я просто из java-world, а в статье это не отражено:

        А вообще, для сборки проекта надо поставить Microsoft Build Tools 2017, после чего запустить из командной строки msbuild находясь в папке проекта — он соберет.

        и для «левого» человека данные моменты могут являться не очевидными.


        1. mayorovp
          28.02.2018 09:41

          Для «левых» людей в репозитории есть папка prebuilt :-)


          1. Skerrigan
            28.02.2018 10:03

            Опять же, мне, левому человеку, это название ни о чем не говорит.
            И да, я программист. Но ЯП иной и своя компоновка как директорий, так и наименований.
            С моей колокольни тут будет «что-угодно», но не результат работы компилятора… скорее сорцы/компоненты, ибо стоит pre (prepared for build?!).

            А так, наш диалог — наглядная иллюстрация «ожидание vs реальность».

            P.S. У меня, к примеру, «выхлоп» идет в директорию target — так же абсолютно не очевидно, что туда будет собран результат компиляции… ибо ну папка с именем «цель», а чего «цель» не понятно. (тут смайлик «развожу руками»)


            1. mayorovp
              28.02.2018 10:22

              Не волнуйтесь, у нас тоже своя компоновка директорий. Бинарники оказываются в папке bin.

              А prebuilt — это авторское изобретение в конкретном репозитории, сделанное человеком который не разобрался зачем на гитхабе придуманы релизы. Переводится как «заранее построенное».


              1. Skerrigan
                28.02.2018 10:29

                «Век живи — век учись» (с).
                Еще раз вам спасибо за помощь!


              1. khim
                28.02.2018 14:08

                А prebuilt — это авторское изобретение в конкретном репозитории,
                Да ладно вам? А это тогда о чём?

                prebuilt — это стандартное название для таких вещей. В Android мире как минимум.

                сделанное человеком который не разобрался зачем на гитхабе придуманы релизы.
                Нет, всё проще — это сделано человеком, который github'ом пользуется только изредка и не хочет менять своих привычек. AOSP'шный prebuilt жил тут ещё 10 лет назад (потом его на части разбили, правда).


                1. mayorovp
                  01.03.2018 13:13

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

                  Что же до слова «prebuilt» — я бы вам поверил что оно существует и без ссылок :-) Под авторским изобретением я понимал элемент структуры директорий, а не слово в отрыве от нее.


                  1. khim
                    01.03.2018 14:28

                    По первой вашей ссылке нет ничего про структуру директорий в репозитории.
                    Потому что git не поддерживает прав доступа. «Структура директорий» описана тут и собирается с помощью repo.

                    Это нормальная практика, в отличии от хранения всего в одной репе вперемешку.
                    Там где нет проблем с правами доступа и проект небольшой — там всё вместе. Вот пример. Вот ещё один. Во втором случае — как раз ситуация, когда было решено, что пора на googlestorage вынести пребилды…

                    Под авторским изобретением я понимал элемент структуры директорий, а не слово в отрыве от нее.
                    Ещё раз: это не авторское изобретение. Это стандартная практика в гугловых проектах.


                    1. mayorovp
                      01.03.2018 14:35

                      А вот это они зря…


                      1. khim
                        01.03.2018 15:17

                        Почему зря? Это удобно и просто. Проблема только в том, что git не очень хорошо работает с бинарными файлами, так что для больших проектов это не годится.


                        1. mayorovp
                          01.03.2018 15:25

                          Это крайне неудобно: нужно в обязательном порядке собирать проект перед каждым коммитом, иначе бинарники окажется нерелевантными. А значит — нужно сначала найти инструкции по сборке всей этой радости (а может быть — даже ОС сменить, тут не проверял).

                          А потом при каждом слиянии — будут лезть конфликты.


                          1. khim
                            01.03.2018 17:44

                            Всё гораздо проще: это делает Commit-Queue бот. И только в основную ветку.

                            Чем это, собственно, отличается от других методов выпуска релизов?

                            P.S. Конечно если вам нужно собирать под разные платформы на разных ботах — этот метод неудобен, это да.


                            1. mayorovp
                              01.03.2018 18:19

                              Отлично, значит разные файлы в одном и том же коммите могут не соответствовать друг другу…

                              Дело не в методе выпуска релиза, а в методе публикации. Основной репозиторий git — неподходящее место для этого.


            1. sumanai
              28.02.2018 15:17

              И да, я программист. Но ЯП иной и своя компоновка как директорий, так и наименований.

              Я вообще PHPшник, где сборка отсутствует как класс. Что не помешало мне потыкать по каталогам и найти бинарник, убедится в том, что он не запускается на XP, поставить студию, сменить версию дотнета, и совершить ещё множество действий при практически полном непонимании синтаксиса, компоновки и прочего.


              1. Skerrigan
                01.03.2018 04:46

                Я из тех, кто сначала «читает ман, потом тыкает/делает».
                Мана нет (Readme), названия не понятные. Пошел спрашивать.


            1. siziyman
              01.03.2018 16:32

              Приставка «pre-» — значит «перед, предварительно». «built» — это «собранный». «prebuilt» — «предварительно собранный». Ну в общем, точно не сорцы.