0

While trying to solve a previously asked SO question of mine, I've find that even without my threads, the problem occurs.

what I have now , is a really simple single-threaded code , that calls - NetServerEnum() . when returned, it calls NetApiBufferFree() and return from main, which supposed to end the process. at that point, my thread truly ends, but the process won't exit , as there are 4 threads opened (not by me):

1 * ntdll.dll!TplsTimerSet+0x7c0 (stack is at ntdll.dll!WaitForMultipleObjects)

(This one opened upon the call to NetServerEnum())

3 * ndll.dll!RtValidateHeap+0x170 (stack is at ntdll.dll!ZwWaitWorkViaWorkerFactory+0xa)

(These are open when my code returns)

UPDATE: If I kill the thread running ntdll.dll!TplsTimerSet+0x7c0 externally (using process explorer) , before return of main(), the program exit gracefully. I thought it might be useful to know.

UPDATE2: (some more tech info) I'm using: MS Visual Studio 2010 Ultimate x64 (SP1Rel) on Win7 Enterprise SP1 Code is C (but compile as c++ switch is on) Subsystem: WINDOWS Compiler: cl.exe (using IDE) all other parameters are default.

I'm Using a self modified entry point (/ENTRY:"entry") , and it is the only function In my program):

int entry(void)
{
SERVER_INFO_101* si;
DWORD a,b;
NET_API_STATUS c;
c = NetServerEnum ( NULL , 101 , (LPBYTE*) &si , MAX_PREFERRED_LENGTH , &b ,  &a  , SV_TYPE_WORKSTATION, NULL , 0 );

c = NetApiBufferFree (si);

Sleep(1000);

return 0;

}

all the tested mentioned before where preformed inside a windows domain network of about 100 units.

UPDATE 3: This problem does not occur when tested on a (non-virtual) WinXP 32bit. (same binary, though for the Win7 x64 two binary were tested - 32bit over WOW , and native x64)

Community
  • 1
  • 1
  • Would you dare to post the full code of your test program? This might be interesting for those how'd like to reproduce what you describe. Also details regarding the environment (OS), compiler and SDK version used could be of help. And last not least as it's about networking a description of the latter would be good to know also. – alk Jun 12 '13 at 20:12
  • By convention, returning from `main` should exit the program whether or not threads are still running. However, this depends on the language, compiler, and runtime library; what are you using? In any case, you should be able to solve the problem by explicitly calling `ExitProcess` instead of returning from `main`. – Harry Johnston Jun 14 '13 at 02:14
  • @alk please tell me If something is still missing – Jim Lanflte Jul 04 '13 at 10:32
  • Which value does `NetServerEnum()` return? – alk Jul 04 '13 at 10:58
  • `NERR_Success` (0) @alk – Jim Lanflte Jul 04 '13 at 12:21
  • @alk also please see update3 (XP32) – Jim Lanflte Jul 04 '13 at 12:37
  • Sry, due the lack of an appropriate environment here, I can not test this ... – alk Jul 05 '13 at 13:29

1 Answers1

0

When you use a custom entry point, you're bypassing the runtime library, which means you're responsible for exiting the process. The process will exit implicitly if there are no more threads running, but as you've discovered, the operating system may create threads on your behalf that you don't have control over.

In your case, all you need to do is to call ExitProcess explicitly at the end of the entry() function.

int entry(void)
{
   SERVER_INFO_101* si;
   DWORD a,b;
   NET_API_STATUS c;

   c = NetServerEnum ( NULL , 101 , (LPBYTE*) &si , MAX_PREFERRED_LENGTH , &b ,  &a  , SV_TYPE_WORKSTATION, NULL , 0 );

   c = NetApiBufferFree (si);

   Sleep(1000);

   ExitProcess(0);
}

In the absence of a call to ExitProcess and with a custom entry point, the behaviour you're seeing is as expected.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • thanks. it is indeed the answer for posted question, yet it's doesn't really solving my issue ( this post is a reduction of my actual problem). My actual problem is that I'm sharing the process with some other functionality of which I have no influence. when my thread is done, I want it to return after it released all of it's resources, including ending all system threads. – Jim Lanflte Aug 12 '13 at 12:23
  • The system threads belong to the process as a whole, not to your particular thread, so terminating them would be a very bad idea. It is the parent processes job to exit properly, can't you speak to whoever is in charge of it? The only other option I can think of would be for your thread to launch a subprocess and do the NetApi work there. – Harry Johnston Aug 12 '13 at 22:02
  • ok, that some how makes sense, even though those system threads were originally created only by function in my thread. anyhow, we can talk physically, but due to management decision we can't affect each other. – Jim Lanflte Aug 13 '13 at 07:29
  • A failure to call ExitProcess is a bug in the parent. Even if it doesn't exhibit now without your DLL, it might do so in the future, e.g., as the result of an implementation change in one of the Win32 API calls used by the parent. Perhaps if you unofficially mention that the problem will go away. :-) Otherwise, the only solution is for your DLL to launch a sub-process, perhaps via `rundll32.exe`. – Harry Johnston Aug 14 '13 at 03:50