The Big Picture: Closing the Restaurant

Every process ends. It might close politely at the end of the day (normal exit), be shut by the landlord (killed), or burn down (crash). Whichever way it ends, Windows has the same cleanup crew: it takes back the memory, closes the open files, and tells anyone who is interested.

 NORMAL EXIT        ABNORMAL (killed)       CRASH (exception)
 program says       someone else says       program does something
 "I'm done"         "stop now"              illegal and is stopped
      \                  |                        /
       +-----------------+------------------------+
                         |
                         v
                  WINDOWS CLEANUP
        (free memory, close handles, record exit code)

3.1 Normal Exit

What it is: The program finishes its job and asks Windows to end it. Windows has a function for this: ExitProcess. Most programs call it for you: when your main function returns, the language's runtime calls ExitProcess.

Things a program usually does first:

  • Saves your files.
  • Closes its windows.
  • Lets each DLL do its own cleanup (the DLLs get a "process is ending" notice).

The exit code. A process ends with a number called its exit code. By long tradition:

Exit codeUsual meaning
0Success, everything went fine
Any other numberSome kind of error or special result; the program's author decides what it means

In Command Prompt, the last exit code is in %ERRORLEVEL%. Try this: cmd /c exit 5 then echo %ERRORLEVEL% prints 5. In PowerShell the same idea is the $LASTEXITCODE variable (for programs you ran) and $? (true or false for the last command).

While a process is running, its exit code is a special value (259, known as STILL_ACTIVE), meaning "not finished yet".

3.2 Abnormal Termination

What it is: The process is stopped by someone else, without being given the chance to tidy up properly. The program did not choose to end.

WayWhat happens
End task in Task ManagerFirst tries to close the window politely; if that fails, kills it
taskkill /PID 1234Asks the program to close (like clicking the X)
taskkill /PID 1234 /FForces it: Windows ends it at once (TerminateProcess)
Stop-Process -Id 1234PowerShell's version; it also terminates forcefully
Shutdown or sign-outWindows asks each program to close, then force-stops those that do not answer

The force option uses the Windows function TerminateProcess. The program gets no chance to save its data or run cleanup code. Unsaved work is lost. That is why you should try the polite way first.

You normally need rights to end a process. You can end your own programs. To end services or other users' processes you need to run as Administrator, and some protected system processes cannot be ended even by an admin.

3.3 Crash / Exception

What it is: An exception is the CPU saying "this instruction is illegal". Examples: reading memory that does not exist (an access violation), dividing by zero, or running a broken instruction. The CPU raises a fault (a type of error trap, see the interrupts section of Chapter 4). Windows catches it and checks whether the program planned for it.

 Illegal action
      |
      v
 CPU fault --> Windows looks for a handler in the program
                    |                    |
              handler found         none found
                    |                    |
              program recovers      process is terminated
                                    (error report may appear)

Programs can include code to handle exceptions (called structured exception handling on Windows; in many languages it looks like try ... catch). If no code handles it, Windows ends the process. You might see a window like "Application has stopped working", and Windows may write a crash dump file (a snapshot of memory) so a developer can investigate. Crash exit codes look like big numbers such as 0xC0000005 (access violation).

Why isolation (Section 1.4) helps: when one process crashes, the others are untouched. Only the kernel crashing takes down the whole PC.

3.4 Cleanup (Memory, Handles, Files)

What it is: When a process dies, Windows does a full cleanup. The process itself does not have to do it, which is why leaks inside one process do not last forever.

ResourceWhat Windows does
ThreadsAll stopped
Virtual memoryThe whole address space is released; the RAM goes back to the free pool (Chapter 3)
HandlesEvery handle in the process's handle table is closed (Section 5)
Open filesClosed, so other programs can use them again (the "file in use" message goes away)
Windows (the GUI kind)Destroyed
Locks and eventsReleased; other processes waiting for them are woken up
The EPROCESSKept for a while, see below

Not everything is cleaned automatically. Things the process created in the outside world may stay: files it wrote, registry entries it made, child processes it started (they keep running, Section 10), and shared memory that other processes still use.

The exit code is stored in the kernel's record. Anyone who holds a handle to the process can ask for it (the function is GetExitCodeProcess).

3.5 Zombie Processes

What it is: On Linux, a zombie is a dead process whose entry is still in the table because its parent has not read its result yet. Windows has no process called "zombie" and no wait() call that forces it, but a similar thing can happen.

On Windows the dead process's kernel record lives on as long as anyone has a handle to it. If a parent (or any program) starts a process and never closes the handle, the process record stays in kernel memory even though the program is long gone. It uses almost no CPU or RAM, but it is a leak.

 Process has exited ---> its code, memory, threads are gone
                           |
                           v
             Small EPROCESS record still exists
             because another program holds a handle
                           |
        holder closes handle ---> record is finally freed

How you may notice this:

  • A process vanishes from Task Manager (its PID is no longer listed as running), yet handle counts of some other program keep growing.
  • Tools like Sysinternals Process Explorer (free from Microsoft, optional) can show these leftover processes.

A related effect: because the PID can be reused after the record is freed, Windows keeps the PID reserved while any handle is open, which prevents mistakes such as "killing the wrong process by an old PID".

The fix is simple: the code that started the process should call CloseHandle on the process handle (and the thread handle) when it is done with them. Closing the program that leaks also releases everything.

Summary

TermPlain meaning
ExitProcessThe program ends itself politely
Exit codeA number left behind; 0 usually means success
TerminateProcessForce-kill: no cleanup by the program
taskkill / /FCommand-line ending; /F means force
ExceptionCPU or program fault; unhandled means the process dies
Crash dumpSnapshot of memory saved after a crash
CleanupWindows frees memory, handles and files; children and written files stay
Zombie-like leftoverDead process record kept alive because a handle is still open