btw, there was deadlock.
I forgot the fact that my thread was sending a internal message before ending, (to log some data) to the thread that was WaitingForSingleObject.
So, ill have to find out another way to do what i wanted to do, but thats another story.
I have lost almost 4 hours thinking the problem was somewhere else and trying to find out wich was it. T_T
Last edited by stratoforce; June 30th, 2009 at 07:40 PM.
Btw, about the message, here is some background:
The problem i have is that i need to send data (some sort of execution report), with statistic data, for the main thread to analyze (wich is also the waiting thread, it has to wait for all threads to terminate before starting to analyze the data, the main thread starts waiting when the user gives the order to "stop doing stuff and start analyzing data").
The solution i applied is Inter Process Communication (Since i have to use it for other stuff too, just need a different message descriptor when im sending messages from worker threads).
The worker thread opens a socket and connects to the main thread (wich is in the same machine) and sends the data.
The main thread has a select() wich has several socket descriptors, since it has to listen to other process in remote machines. (those process are different from the local threads, they do different jobs).
So a deadlock happens when the user gives the order to stop, and the main thread starts to WaitForMultipleObjects, since it is blocked, cannot accept the connection from the worker threads, wich means that the workers will never end. xD
Yes, the design is awful, but when i started coding this process we were not going to wait for all the threads to finish before starting the data analisys.
The only way i can think of to solve this is without changing everything is to WaitForMultipleObject in an aditional thread.
Again thanks for your help and interest.
Last edited by stratoforce; July 1st, 2009 at 03:53 PM.
As I understand, you are working within the same process. If that's the case, the you might consider another logging approach other than using sockets.
I probably am in the minority here, but I don't even like to pass data by sending windows messages between threads. Sure I send messages between threads, but only to signal another thread and seldom include data in the message. My preference is to use a shared queue and have the secondary threads push items onto the queue and have a worker threads or the UI thread process (pop) the queue items.
That being said, consider using a few event types: a pending shutdown, shutdown event and have each thread create and set an acknowlege pending shutdown event. For this scenario consider that the socket log processing is performed in a separate thread.
The shutdown sequence would work as follows:
1) Set the pending shutdown event first in the main thread. When the threads receive that event, they perform all their logging and then set their own ack pending event.
2) The main thread then waits for multiple objects on each thread ack pending event.
3) The main thread sends a shutdown event which causes the threads to exit (include the log processing thread). In the case where sockets are used for logging, by the time the shutdown event is received, there shouldn't be any remaining socket connections so the log service thread can close without issue. If you go with a queue to pass log data, the thread can shutdown after processing all log requests (because you can be assured that additional requests won't be put in the queue).
4) The main thread uses wait for multiple objects on the thread handles before exiting.
Sorry, i failed to give enough details about my problem.
The shared queue is very interesting, (i wanted to know alternatives to share data between threads anyways, and this approach is very interesting), but i cannot apply it in this proyect because we are not allowed to use shared memory between threads.
Each thread can access only his own heap. So, ill have to keep the queue private.
About the "pending shutdown>ack>shutdown".
In this particular case, i don't have control of when a worker thread ends. (i can only stop creating threads, but cannot stop them).
I could let the main thread know when the workers finish sending the log data, to the logging thread with an event.
But i would still need an aditional thread if i don't want to block the main thread (if that happens i cannot recv the log data from the threads).
There are chances the requirements change again, and we no longer require to wait for all the threads to finish.
But in case the requirements don't change, the solution ill apply will be:
a) Aditional thread to log
b) Aditional thread to wait (i have one thread that does not do much and can be blocked when the time to close everything comes, so i could use that one).
Last edited by stratoforce; July 1st, 2009 at 09:52 PM.
1. The main thread uses (asynchronous, I believe) socket. It works only for non-blocked main thread (message queue must be pumped), while it gets eventually blocked intentionally by wait function.
2. Using wait function in main (GUI, I believe) thread. Very rare approach for a professional application. The more appropriate solution is to run a separate 'supervising' thread that monitors the state of all the other ones and notifies the GUI thread by posting a dedicated message. The additional thread results in a tiny overhead.
3. Logging with sockets. As long as the logging happens within the same process, the sockets seem overcomplicating. Pipes would look more natural here, at least for me. But what I would really suggest is a single logger object that would incapsulate and serialize logging operations. The object internals could vary in future but the call interface would remain stable. The consumers must not be aware about the service object details.
4. Shutdown signal sent through communication channel (as I understand). I really dislike the approach for stopping threads. My typical approach is a "shutdown" event object all the worker threads wait for (with WaitForMultiple... of course). Besides, I do not understand why the main thread should wait for stopping the worker ones while it just could stop accepting logging events.
I finally ignored logs once the main thread gives the order to stop.
Thanks for your advices , I will answer now:
1. The main thread should not block in this particular proyect, since it is listening for incoming request from remote machines.
2. This is a console application, no GUI for us. And im a newbie trying to learn, not professional. T_T
3. Logging in a separate thread is an idea i like, and maybe i will use in future proyects
4. I needed (not anymore) to wait for all the thread to log everything, if i just ignore logs (i ignore them now) ill loose some data, but its ok, since i got green light on that from my proyect supervisors.