Windows – (When) is CONHOST.EXE actually necessary

conhostconsoleprocesswindows 7

Background

Last year I compiled a portable blog/web-server system that I can run from a flash-drive. It’s great and works wonderfully, especially on XP. The problem is that when it’s run in Windows 7, each console program spawns two process, the process itself, plus a copy of conhost.exe.

Problem

In the case of the portable blog system, each one of its server components (MySQL’s mysqld.exe, Apache’s two instances of httpd.exe, VisualSVN’s two instances of visualsvnserver.exe, and PHP’s multiple instances of php-cgi.exe) spawns an instance of conhost.exe. At this moment (with no copies of php-cgi.exe active, I have five instances of conhost.exe running, using up next to no CPU cycles, but consuming 22MB of memory (in addition to the 80MB that the actual processes are currently using).

Research

Since Windows 7 was released (and I think possibly since Vista), I have on several occasions tried to figure out exactly what purpose the various (new) host processes (e.g., conhost.exe, dllhost.exe, and taskhost.exe) do and whether they are actually necessary. I have tried killing them and found that the console programs continue to work, both for programs that use a console window, and those that don’t (like servers).

I am already familiar with the whole csrss.exe ⇨ Windows Vista ⇨ conhost.exe and have seen that same (almost verbatim) explanation numerous times. The problem is that everybody simply copy-pastes that same explanation which is not helpful. All it says is that in XP-, console applications where “hosted by” or “run under” csrss.exe, but in Windows 7, they were moved to conhost.exe for security. The security aspect makes sense, but it says nothing about what it means to host it or why/when it’s necessary (or whether it’s possible to avoid it if not necessary). Even Raymond Chen’s discussion on the matter glosses over why console apps are hosted differently at all.

The closest thing I can find to a detailed, technical explanation is a Microsoft blog post which seems to reinforce the idea that it’s merely about the console app’s GUI and window. This leaves me wondering even harder whether conhost.exe is necessary for windowless programs like these servers. If there is no window at all, then why should I have to waste resources and clutter the process-space with unnecessary processes? Why can’t Windows detect when it’s unnecessary and avoid it? SecurityMatt’s response was also slightly useful in regards to a technical explanation, but again, not enough of the information I’m looking for.

I’m not the only one who has tried to figure out a way to stop unnecessary instances of conhost. This person asked about disabling it and was told simply “it’s not possible” with no further effort or thought about it. Hugh D and “Hardly a feature” pointed out the issue with numerous, redundant instances of conhost (at least with csrss, there was only a single copy running), including the resource usage and lingering instances after their child processes have ended. I Laufer questioned whether/when it’s even necessary.

Observations and Solution Attempts

If they are not actually necessary at all times (again, I have not seen any ill effects from killing them), then I suppose I could (very irritatingly) work-around the issue by replacing the servers with batch-files that run the servers, wait, and then kill the copy of conhost that they cause to run. Of course this requires a quick and easy way of determining which one it is. FallenGameR asked how to get the instance of conhost.exe associated with a console program of a given PID but did not get an answer. I would think that simply retrieving the PID of the parent process should do the trick (no, ProcessExplorer is not an option, an automated/scriptable solution is required), but not only would that require creating some sort of framework to get the PID of the child (instead of simply running it and being done with the task), but it would also mean figuring out a way to make it compatible with XP as well (e.g., checking the image-name of the parent process). This blog post gives one way, but it requires PowerShell and is hardly ideal, not to mention it says nothing about the ramifications of running the script.

Question(s)

Perhaps Microsoft figure that nobody uses command-prompts anymore (*cough*Windows 8*cough*) and so assumed that it’s not a big deal to burden them, but there are definitely scenarios where multiple console apps are running and having each and every one spawn an extra, memory-consuming, PID-using process is awful, and trying to work around it is, at best, horribly inconvenient.

Does anybody have definitive, authoritative information on the matter? Again, I have already read the generic explanation; I am wondering:

  1. Why console applications must (still) be handled differently at all
  2. Under what specific circumstances they need to have conhost
  3. What the consequences are of killing conhost
  4. If there’s any way to stop/prevent/disable/block it or at least an easy way to quickly deal with it aftwards?

Best Answer

  1. Console applications must be differently handled because under the NT kernel (which underlies all of 2000, XP, Vista, Windows 7, and Windows 8) they are second-class citizens. In the Unix system architecture, every process at creation time has the standard input, output, and error streams attached to it; terminal IO is implemented in terms of these streams (stdin coming from the keyboard, and stdout/stderr going to the terminal), and extra effort is required on the part of a process which doesn't wish to make use of those streams or have their file descriptors open.

    In the Windows NT architecture, which while not a lineal descendant of VMS was developed by more or less the same team, the opposite is true; a newly spawned process by default has no I/O streams connected to it at all, and there is no such concept as a "terminal". Programs which wish to behave in a slightly more Unixy fashion may request (by compile-time declaration) that the system create for them a console window, and input/output streams connected to it; the system will do so, but since Windows, unlike Unix, doesn't give you terminals for free, a considerable amount of additional effort is required to create one, thus formerly csrss.exe, and now conhost.exe.

    As for the difference between the two, your "Hardly a feature" link explains it quite adequately; in short, it exists to work around a security flaw in the previous iteration of Windows's highly recondite console API, which allowed for privilege escalation in versions of NT older than Windows 7. (Vista, FYI, does not have conhost.exe, which is befitting of its status as the Windows Millennium of the NT family.)

  2. Any program which wants the equivalent of Unix stdin/stdout/stderr needs a console, hence an instance of conhost.exe. Immigrants from Unix-land, such as Apache, PHP, et al., are going to want these streams, hence the system's automatic instantiation of conhost.exe for them, whether they actually display a window or not. In theory, it would be possible to modify the source for e.g. Apache such that it required no terminal, and compile it as a Windows GUI application instead of a console application, so that the system wouldn't feel the need to spawn it a conhost.exe. Assuming it's also possible in practice, no one seems to have cared enough to do so. Perhaps you will be the first.

  3. Killing a given conhost.exe will almost certainly disable console IO for whatever process is running under that instance. You probably don't care about that because you're dealing with server processes that aren't doing anything interesting on the console IO streams anyway, so there's probably no reason not to kill their conhost.exes. If in doubt, kill them off and see if it breaks anything.

  4. There is no way to prevent Windows from instantiating conhost.exe when a program is launched which requests console IO; the only way to do so would be to recompile it so that Windows doesn't regard it as a console application. However, assuming that killing a given server process's parent conhost.exe doesn't impair its functionality in any way you care about, you should be able to kill them all at once by issuing taskkill /f /im conhost.exe in a Run prompt or a console window -- preferably the former, since the latter will probably die, and almost certainly cease to work, as soon as its parent conhost.exe instance is killed. Again, if in doubt, kill them off and see if it breaks anything.

Related Question