Click to See Complete Forum and Search --> : Stumped by weird "crash"


shoppinit
January 16th, 2010, 11:10 AM
Hi,

I hope this is the right place to post my problem. My VS data aquisition program is running on a quad core intel PC running XP pro SP3. Almost nothing else is running other than system processes. Occasionally - say 1 to 4 times a day - the PC will appear to freeze up. I say appear, because the system isn't frozen, but just extremely slow to respond. Last time I was able to start task manager (took 3 minutes to display the window) and 2 of my cores are at about 100% and the other 2 at about 60%.

Task manager is reporting ~80% CPU usage, but System Idle Process is showing ~75%. This clearly doesn't make any sense.

I initially thought that I had written a while(1) into my code somewhere, but when killed my processes from task manager the problem remained. I then killed as many system processes as I was allowed to without any luck... A reboot sets everything straight, but I would really like to get to the bottom of this problem.

I'm wondering if somehow I have some kind of "thread leak". i don't even know if that is possible. I've checked all the thread creations and destructions in my code and nothing seems remotely dangerous. My fear is that one of my 3rd party APIs is to blame.

I'm even starting to wonder if this problem isn't heat related, so I must be desperate!

Can anyone suggest some way of starting to pinpoint the problem? Any suggestions gratefully received.

Thanks.

Arjay
January 16th, 2010, 06:54 PM
If you kill your process with task manager, does the system start responding again?

shoppinit
January 17th, 2010, 07:08 AM
No, this is the first thing I tried and the system remains in its super slowed down state.

I have one thread that is at highest priority, but this thread is just waiting for serial port events and dispatching info to other threads, so it shouldn't to use any CPU time. Even if it did, killing the process should restore normal system speed.

Arjay
January 17th, 2010, 12:09 PM
Put a Sleep(50) statement inside the highest priority thread for testing purposes and see if the system performance improves. If it does, then you know you have an issue in that thread while it's waiting.

shoppinit
January 17th, 2010, 12:36 PM
Thanks for the suggestion. I'll put a Sleep in there. Would a Sleep(0) allowing a context change be useful, or would the high priority thread just be scheduled again?

Looking a bit closer, I've effectively got the following :


while(true)
{
::WaitCommEvent(...
switch (::WaitForMultipleObjects(sizeof(ahWait)/sizeof(*ahWait),ahWait,FALSE,INFINITE))
{
case WAIT_OBJECT_0:
{...}
case WAIT_OBJECT_0+1:
{...}
default:
{...}

}
}

So if something goes wrong with the serial port, I guess I'd be immediately returning from WaitCommEvent and going to my default case, so effectively a while(1)...

Arjay
January 17th, 2010, 02:25 PM
My feeling is that something is going wrong in the high priority thread and suggested adding the sleep to see if you notice a change in perf. You'll want to add the sleep inside the while(1) loop - anywhere is fine as long as it gets called each time in the loop.

Adding the sleep is just a temporary debugging technique. If you write the thread properly, it should be sleeping most of the time until it receives a com event.

Sleep(0), although causing a context switch, will only relinquish the remainder of the current time slice. Since the thread scheduler always runs high priority threads before lower priority threads, Sleep(0) will not help much here other than allowing other high priority threads to run. However, above normal, normal and lower threads still won't be scheduled to run. You'll still experience a sluggish UI because most UI threads run at normal priority.

Using Sleep(50) is just one debugging technique - another would be to drop the thread priority of the COMM svc thread to normal. I suspect you'll see the system UI response turn to normal, unfortunately you won't want to leave this thread this way, because it's likely that you'll lose data.

You may throw in some ASSERT and/or TRACE statements within the while loop. If the default case is an error condition, call GetLastError and return from the thread. Use GetExitCodeThread in the thread that started the COMM svc thread to determine the error.

majic79
January 19th, 2010, 05:22 AM
you could easily tidy up your WaitCommEvent call - check the return value, if its non-zero, then it came back straight away, and you wont need to wait for the handle. You really only need to be waiting for the handle if the return value is zero and GetLastError is ERROR_IO_PENDING.


if(::WaitCommEvent(...))
{
// Stuff
}
else
{
if(GetLastError() != ERROR_IO_PENDING)
{
// Some other system error!
}
else
{
::WaitForMultipleObjects(....);
}
}