As said, console processes always terminate this way.
Just for the record, all processes that end _normally_ whether console or GUI, end with a call to ExitProcess. In a language such as Pascal, the call is not visible because it is part of the RTL. Also, there are other ways to terminate a process but none of them are considered normal and/or desirable.
Recently I had a C++ Windows GUI program, dealing with threads, that did not fully terminate, because not all Threads where terminated.
The threads where I/O blocked and could not self terminate.
I tested the behaviour of a Free pascal Program with threads and indeed it terminates when the close button is pressed despite threads running.
In this case however, gdb does not terminate, so there is still something wrong. At a subsequent debug session there are problems.
(I started the thread with BeginThread, dont know if that matters) Now I must reboot, all ghost processes removed, but still problems with debugging.
the debuggee terminates not, if an unhandled exception e.g. 1/0 happens.
So a call to Exitprocess in an exception handler could be required in this case.