{"id":2433,"date":"2013-12-09T07:00:00","date_gmt":"2013-12-09T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/12\/09\/destroying-all-child-processes-and-grandchildren-when-the-parent-exits\/"},"modified":"2013-12-09T07:00:00","modified_gmt":"2013-12-09T07:00:00","slug":"destroying-all-child-processes-and-grandchildren-when-the-parent-exits","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20131209-00\/?p=2433","title":{"rendered":"Destroying all child processes (and grandchildren) when the parent exits"},"content":{"rendered":"<p>\nToday&#8217;s Little Program\nlaunches a child process\nand then just hangs around.\nIf you terminate the parent process,\nthen all the children (and grandchildren and\ngreat-grandchildren, you get the idea)\nare also terminated.\n<\/p>\n<p>\nThe tool for this is the\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms684161(v=vs.85).aspx\">\nJob Object<\/a>.\nSpecifically, we mark the job as\n&#8220;kill on job close&#8221;\nwhich causes all processes in the job to be terminated\nwhen the last handle to the job is closed.\n<\/p>\n<p>\nWe must therefore be careful not to allow this handle to be inherited,\nbecause that would create another handle that needs to be closed before\nthe job is terminated.\nAnd of course we need to be careful not to close the handle unless we\nreally do want to terminate the job.\n<\/p>\n<pre>\n#define STRICT\n#include &lt;windows.h&gt;\nBOOL CreateProcessInJob(\n    HANDLE hJob,\n    LPCTSTR lpApplicationName,\n    LPTSTR lpCommandLine,\n    LPSECURITY_ATTRIBUTES lpProcessAttributes,\n    LPSECURITY_ATTRIBUTES lpThreadAttributes,\n    BOOL bInheritHandles,\n    DWORD dwCreationFlags,\n    LPVOID lpEnvironment,\n    LPCTSTR lpCurrentDirectory,\n    LPSTARTUPINFO lpStartupInfo,\n    LPPROCESS_INFORMATION ppi)\n{\n    BOOL fRc = CreateProcess(\n        lpApplicationName,\n        lpCommandLine,\n        lpProcessAttributes,\n        lpThreadAttributes,\n        bInheritHandles,\n        dwCreationFlags | CREATE_SUSPENDED,\n        lpEnvironment,\n        lpCurrentDirectory,\n        lpStartupInfo,\n        ppi);\n    if (fRc) {\n        fRc = AssignProcessToJobObject(hJob, ppi-&gt;hProcess);\n        if (fRc &amp;&amp; !(dwCreationFlags &amp; CREATE_SUSPENDED)) {\n            fRc = ResumeThread(ppi-&gt;hThread) != (DWORD)-1;\n        }\n        if (!fRc) {\n            TerminateProcess(ppi-&gt;hProcess, 0);\n            CloseHandle(ppi-&gt;hProcess);\n            CloseHandle(ppi-&gt;hThread);\n            ppi-&gt;hProcess = ppi-&gt;hThread = nullptr;\n        }\n    }\n    return fRc;\n}\n<\/pre>\n<p>\nThe\n<code>Create&shy;Process&shy;In&shy;Job<\/code> function\nsimply creates a process suspended, adds it to a job,\nand then resumes the process if the original caller\nasked for a running process.\n<\/p>\n<p>\nLet&#8217;s take it for a spin.\n<\/p>\n<pre>\nint __cdecl main(int, char **)\n{\n HANDLE hJob = CreateJobObject(nullptr, nullptr);\n JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = { };\n info.BasicLimitInformation.LimitFlags =\n                    JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;\n SetInformationJobObject(hJob,\n       JobObjectExtendedLimitInformation,\n       &amp;info, sizeof(info));\n STARTUPINFO si = { sizeof(si) };\n PROCESS_INFORMATION pi;\n char <a HREf=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2009\/06\/01\/9673254.aspx\">szCommandLine<\/a>[] = \"taskmgr.exe\";\n if (CreateProcessInJob(hJob,\n     \"C:\\\\Windows\\\\System32\\\\taskmgr.exe\",\n     szCommandLine,\n     nullptr, nullptr, FALSE, 0,\n     nullptr, nullptr, &amp;si, &amp;pi)) {\n  CloseHandle(pi.hProcess);\n  CloseHandle(pi.hThread);\n }\n Sleep(30 * 1000);\n CloseHandle(hJob);\n return 0;\n}\n<\/pre>\n<p>\nAfter creating the job object,\nwe set the &#8220;kill children on close&#8221;\nflag on the job.\nThen we launch Task Manager into the job\nand give you 30 seconds to\ndo your business.\nAfter that, it&#8217;s &#8220;Time&#8217;s up, you lose!&#8221;\nand Task Manager and any processes you launched from Task Manager\nwill go away.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today&#8217;s Little Program launches a child process and then just hangs around. If you terminate the parent process, then all the children (and grandchildren and great-grandchildren, you get the idea) are also terminated. The tool for this is the Job Object. Specifically, we mark the job as &#8220;kill on job close&#8221; which causes all processes [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-2433","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Today&#8217;s Little Program launches a child process and then just hangs around. If you terminate the parent process, then all the children (and grandchildren and great-grandchildren, you get the idea) are also terminated. The tool for this is the Job Object. Specifically, we mark the job as &#8220;kill on job close&#8221; which causes all processes [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2433","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=2433"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/2433\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=2433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=2433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=2433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}