Thread problem (chase your own tail)

There ConnectionManager

is one waiting for incoming connections. For each inbound connection, an instance is created Connection

that processes the inbound and outbound traffic on that connection. One Connection

has Watchdog

one that handles "bad connection" conditions and calls the "Listerners" entries. One "listener" is one ConnectionManager

that closes the connection and removes the instance Connection

, which in turn removes the corresponding watchdog timer.

Wait. A. Minute.

Watchdog

calls ConnectionManager

, which removes Connection

, which removes Watchdog

? The watchman chases his own tail.

I am completely blocked. How do I resolve this?


Solution . I'll make the listener asynchronous, although I don't know yet how to do this without too much trouble. Watchdog

does not know about ConnectionManager

. This is pretty general. Also, the Win32-Thread-API doesn't have something like "join", so I might need to collapse it with GetExitCodeThread()

and STILL_ACTIVE

...

Thanks guys.

+1


source to share


4 answers


If the watchdog is running on a different thread, the problem is not too bad - the watchdog signals that the ConnectionManager is deleting with an asynchronous message and then exits on its own thread.

On average, the ConnectionManager thread receives the delete message and starts deleting the watchdog timer.



To avoid race conditions, the watchdog destructor must attach to the watchdog thread and clean up the stream. (Maybe also signal the watchdog or assert () something that the watchdog is ready to exit).

+2


source


Messages.

Instead of having Watchdog call the method ConnectionManager

, post a message to the queue in the connection manager. This queue must be thread safe. When ConnectionManager

processing a queue on its own thread, it will be safe to wait for the Connection thread to complete.



Watchdog          Queue               ConnectionManager
   |                |                        |
Kill Connection---->|                        |
   |                |<-------------------Get Message
  ---               |                        |
                    |-------------------->Process Message
                    |                        |
                    |                     Kill Connection

      

+3


source


If each of these objects is running on its own thread, there is no problem.

Watchdog notifies ConnectionManager and returns.
At this point, the Watchdog thread may simply exit.

When the ConnectionManager observes a watchdog event, it kills the Connection thread.

+2


source


If you are careful, there is no problem.

  • ConnectionInstance :: a_method () calls Watchdog :: a_method () calls ConnectionManager :: a_method

  • ConnectionManager :: a_method () removes ConnectionInstance removes Watchdog

  • ConnectionManager :: a_method () falls back to Watchdog :: a_method () returns ConnectionInstance :: a_method (). As long as the return path does not have access to any elements, it is just a return from a function. The code still exists by standard, so you can safely come back.

This requires careful coding and maintenance, but this is not a dirty hack it might sound like.

An asynchronous protocol will require the same amount of thinking. It's not only that you need to avoid races between the Watchdog requesting deletion in the queue, ConnectionManager :: and ConnectionManager, doing something to the queue at the same time. The problem is deeper: there is a period of time when ConnectionInstance is down - it asked to be removed, but it hasn't been removed yet. What is he doing? The code cannot remain stationary. If there is a safe way out for an unsuitable ConnectionInstance, you can also roll back the stop yourself without creating any additional asynchronous protocols.

A watchdog throwing an exception might be an easier way to deal with ConnectionInstance if they are on the same thread.

0


source







All Articles