Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TIdUDPServer locks up in DLL on finalization


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 4 - Last Post: Oct 23, 2015 10:32 AM Last Post By: Wade Christensen
Wade Christensen

Posts: 5
Registered: 4/9/97
TIdUDPServer locks up in DLL on finalization  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 22, 2015 3:09 PM
I have a library (DLL) that uses TIdUDPServer. It seems that if I set TIdUDPServer.Active to false (call from main app to dll routine) before I unload the DLL everything works as expected. However, if I don't set it to false or if I set it to false in the unit's finalization block (or in library exit code), TIdUDPServer gets stuck in deadlock. The routine TIdUDPServer.CloseBinding calls LListener.WaitFor; where the deadlock happens.

So...What is the proper way to cleanup when a library is unloaded without locking everything up?

Not sure what version of Indy, but this is an XE5 project.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TIdUDPServer locks up in DLL on finalization  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 22, 2015 4:35 PM   in response to: Wade Christensen in response to: Wade Christensen
Wade wrote:

However, if I don't set it to false or if I set it to false in the unit's
finalization block (or in library exit code), TIdUDPServer gets stuck
in deadlock. The routine TIdUDPServer.CloseBinding calls
LListener.WaitFor; where the deadlock happens.

So...What is the proper way to cleanup when a library is unloaded
without locking everything up?

Don't wait until the library is finalized before deactivating the server.
Make the app do it before unloading the library. Creating and stopping
threads from inside a DLL's entry point function is dangerous:

Does creating a thread from DllMain deadlock or doesn't it?
http://blogs.msdn.com/b/oldnewthing/archive/2007/09/04/4731478.aspx

This deadlock is much more commonly seen in DLL_PROCESS_DETACH, where a DLL
wants to shut down its worker threads and wait for them to clean up before
it unloads itself. You can't wait for a thread inside DLL_PROCESS_DETACH
because that thread needs to send out the DLL_THREAD_DETACH notifications
before it exits, which it can't do until your DLL_PROCESS_DETACH handler
returns.

Deadlock because the unit finalization is waiting for TIdUDPServer to deactivate,
but TIdUDPServer is waiting for its listener thread to terminate, but the
thread is waiting for unit finalization to finish.

--
Remy Lebeau (TeamB)
Wade Christensen

Posts: 5
Registered: 4/9/97
Re: TIdUDPServer locks up in DLL on finalization  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 22, 2015 9:31 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Don't wait until the library is finalized before deactivating the server.
Make the app do it before unloading the library. Creating and stopping
threads from inside a DLL's entry point function is dangerous:

That is how the library is designed (there is a cleanup function that should be called). However, as this is a DLL used by other applications, I can't ensure that the calling app will call the cleanup function before unloading the application. If the calling app unloads the DLL without calling the cleanup function you really don't want the entire application to lockup.

Does creating a thread from DllMain deadlock or doesn't it?
http://blogs.msdn.com/b/oldnewthing/archive/2007/09/04/4731478.aspx

I'll have to create on one in DLLMain to see what happens, but I would expect a deadlock based on that info. In my case, I'm not creating it in DLLMain, but I am trying to free the component/threads in the unit's finalize section if the calling app fails to clean up.

This deadlock is much more commonly seen in DLL_PROCESS_DETACH, where a DLL
wants to shut down its worker threads and wait for them to clean up before
it unloads itself. You can't wait for a thread inside DLL_PROCESS_DETACH
because that thread needs to send out the DLL_THREAD_DETACH notifications
before it exits, which it can't do until your DLL_PROCESS_DETACH handler
returns.

Deadlock because the unit finalization is waiting for TIdUDPServer to deactivate,
but TIdUDPServer is waiting for its listener thread to terminate, but the
thread is waiting for unit finalization to finish.

--
Remy Lebeau (TeamB)

Thanks for the info & link, I'll review it.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TIdUDPServer locks up in DLL on finalization  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 22, 2015 11:52 PM   in response to: Wade Christensen in response to: Wade Christensen
Wade wrote:

I can't ensure that the calling app will call the cleanup function before
unloading the application.

You are going to have to. It is a requirement. Make sure your DLL users
are aware that proper cleanup is needed or bad things can happen.

If the calling app unloads the DLL without calling the cleanup function
you really don't want the entire application to lockup.

You don't have a choice. When a DLL is unloaded, there are only a few things
it is allowed to do during its finalization, and managing threads is not
one of them.

I'll have to create on one in DLLMain to see what happens, but I would
expect a deadlock based on that info.

In my case, I'm not creating it in DLLMain, but I am trying to free the
component/threads in the unit's finalize section if the calling app fails
to clean up.

Delphi's initialization and finalization actions are calls in the context
of the DLL's entry point function, which is hidden inside the depths of the
RTL. As such, it is not safe to wait on a worker thread during DLL finalization.
Guaranteed deadlock. And that is exactly what you are seeing happen if
you try to deactivate the server during finalization - it waits on a thread
that becomes deadlocked because finalization is blocking it from terminating
correctly.

--
Remy Lebeau (TeamB)
Wade Christensen

Posts: 5
Registered: 4/9/97
Re: TIdUDPServer locks up in DLL on finalization  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 23, 2015 10:32 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB)

Well, that's unfortunate. I swear I've used DLL's before that had threads and didn't have a cleanup function, but I can't think of one. In this case, I'm adding the udp server to an existing DLL that callers use and don't currently call a clean up, so that breaks backwards compatibility for old apps, but it is what it is.

At any rate, thanks for the information.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02