Click to See Complete Forum and Search --> : crash at dwRes = WaitForSingleObject(*m_hSemaphore, 45000);


mohamed123
September 5th, 2005, 11:35 AM
here is my code for making a pic from a camera

**************
void CPreviewTestDlg::OnCapture()
{
GetDlgItem(IDC_BTNCAPTURE)->EnableWindow(FALSE);
if(cam1Connected)
{
if(strName!="NOSELECTION")
{
waitPreviewThread(&m_hSem);
cam1Capture = TRUE;
cam1PicCounter++;
getFileName(cam1PicCounter);
CaptureCam(0);
cam1Capture = FALSE;
ReleaseSemaphore(m_hSem, 1, NULL);
}
else
{
MessageBox("No Product Id Selected","Product Id",MB_ICONEXCLAMATION);

}

}
else
{

MessageBox("Camera 1 Not Connected ! ","Connection Error",MB_ICONEXCLAMATION);

}
}
**************

i want to call this function twice so ii made a func called

CaptureTwice()

and called the func but it crashes exactly at


void CPreviewTestDlg::waitPreviewThread(HANDLE * m_hSemaphore)
{
DWORD dwRes;
// wait for the preview thread to stop

dwRes = WaitForSingleObject(*m_hSemaphore, 45000);
if (dwRes == WAIT_TIMEOUT)
{
AfxMessageBox(_T("Camera timed out."), MB_OK);
return;
}
}

it crashes at dwRes

i am new to multithreading any idea why ?? would be helpful

regards
mohamed

Eli Gassert
September 5th, 2005, 12:19 PM
To make your life easier, I'd look into use the CSingleLock class.

Check it out at MSDN. It makes things much easier in my opinion.

Attached is an example of how I've use it:

in my .H file

CCriticalSection m_csSynch;


in my .cpp file

....
CSingleLock lock(&m_csSynch);

lock.Lock();
if(lock.IsLocked())
{
i = m_lstMessages.begin();

// nothing to send? don't connect if empty
if(i == m_lstMessages.end())
{
lock.Unlock();
return TRUE;
}
}
else
{
lock.Unlock();
return FALSE;
}

if(!smtp.Connect())
return FALSE;

....


The nice thing about a single lock is once the local variable for that lock goes out of scope -- be it the function ends or (what's more important!) the function somehow crashes and you never unlock the critical section -- the class unlocks for you in its deconstructor.

So, instead of passing a handle around and what not, I would use a CCriticalSection as your base object and wrap it in a CSingleLock, which would take away the use of your wait for.

HTH

mohamed123
September 5th, 2005, 01:35 PM
hi thans for the reply

but the main problem i face is lack of understanding of

why we waitforsingleobject

i found out that when i

OnCapture();
MessageBox
OnCapture2();

the program works fine

but without messaage box or

OnCapture();
Sleep
OnCapture2();

the program crashes at dwResvoid CPreviewTestDlg::waitPreviewThread(HANDLE * m_hSemaphore)
{
DWORD dwRes;
// wait for the preview thread to stop
dwRes = WaitForSingleObject(*m_hSemaphore, 45000);
if (dwRes == WAIT_TIMEOUT)
{
AfxMessageBox(_T("Camera timed out."), MB_OK);
return;
}
}
My question isnt it allowed to access or waitforsingleobject twice ?
And why does it work when i use a messagebox , does messagebox clear something or does it give a delay ? Then why doesnt Sleep work

Regards
Mohamed

mohamed123
September 5th, 2005, 06:11 PM
hi
thanx for the reply

but i did not have problem when i call waitforsingleobject first time
it did not even give a compiler error
and
one more point
the code works when i use a message box between first and second call for waitforsingleobject the code works perfectly

one question does waitforsingleobject , makes the m_sem wait ??
and is i use releasesemaphore does this thread start again ??
regards
mohamed

Siddhartha
September 5th, 2005, 06:40 PM
but i did not have problem when i call waitforsingleobject first time
it did not even give a compiler errorPlease post your declaration of m_hSemaphore.

Compilation Success does not imply correct API usage.one question does waitforsingleobject , makes the m_sem wait ??Do you mean m_hSem??

WaitForSingleObject does not return till the state of the object is signaled. In that sense, WaitForSingleObject makes the current thread wait (and not any semaphore wait... Semaphore is an Event Object that can get signalled -- releasing the wait.)

is i use releasesemaphore does this thread start again ??ReleaseSemaphore will increment the Semaphore Usage count.

The semaphore will get signalled only when - The state of a semaphore is signaled when its count is greater than zero and nonsignaled when it is zero. The count is decreased by one whenever a wait function releases a thread that was waiting for the semaphore. The count is increased by a specified amount by calling the ReleaseSemaphore function. Also post your CreateSemaphore code...

mohamed123
September 5th, 2005, 06:57 PM
hi

heres where semaphore is created

void CPreviewTestDlg::SetPreview1()
{
// TODO: Add your control notification handler code here
RECT rc;


// initialize the VARIANT array to hold the preview data
// do it once with a large enough buffer so we don't waste
// time each preview
m_arPreview.CreateOneDim(VT_UI1, 65536);

// save the DC information for the preview window
// only need to do this once since it won't change
m_dcPreview = m_Preview.GetDC()->m_hDC;
m_Preview.GetClientRect(&rc);
m_nPreviewHeight = rc.bottom - rc.top;
m_nPreviewWidth = rc.right - rc.left;

// create a semaphore object to syncronize the preview thread
// with the main thread so we don't try to access the camera
// from two threads at the same time
m_hSem = CreateSemaphore(NULL, 1, 1, NULL);

// start the preview thread
m_pThread = AfxBeginThread(PreviewFunc, this);


}

Siddhartha
September 5th, 2005, 07:00 PM
I shall look into your code tomorrow... Its late night here, and actually I just realized that m_hSemaphore above is a pointer to a handle, and hence the WaitForSingleObject Statement is seemingly ok.

I'll reply tomorrow... If I do so now I might make mistakes. :)

In the meanwhile, please post as much code as you can... especially that pertaining to OnCapture and OnCapture2...

mohamed123
September 6th, 2005, 05:19 AM
void CPreviewTestDlg::OnCapture()
{
GetDlgItem(IDC_BTNCAPTURE)->EnableWindow(FALSE);
if(cam1Connected)
{
if(strName!="NOSELECTION")
{
waitPreviewThread(&m_hSem);
cam1Capture = TRUE;
cam1PicCounter++;
getFileName(cam1PicCounter);
CaptureCam(0);
TRACE("returned to oncapture");
cam1Capture = FALSE;
ReleaseSemaphore(m_hSem, 1, NULL);
}
else
{
MessageBox("No Product Id Selected","Product Id",MB_ICONEXCLAMATION);
}

}
else
{
MessageBox("Camera 1 Not Connected ! ","Connection Error",MB_ICONEXCLAMATION);
}
GetDlgItem(IDC_BTNCAPTURE)->EnableWindow(TRUE);
}

void CPreviewTestDlg::OnCapture2()
{
if(cam2Connected)
{
if(strName!="NOSELECTION") // unless a product id is selected picture cannot be taken
{
waitPreviewThread(&m_hSem2);
cam2Capture = TRUE;
cam2PicCounter++;
getFileName(cam2PicCounter);
GetDlgItem(IDC_BTNCAPTURE2)->EnableWindow(FALSE);
CaptureCam(1);
cam2Capture = FALSE;
// release the semaphore so the preview thread can start up again
ReleaseSemaphore(m_hSem2, 1, NULL);
}
else
{
MessageBox("No Product Id Selected","Product Id",MB_ICONEXCLAMATION);

}

}
else
{
MessageBox("Camera 2 Not Connected ! ","Connection Error",MB_ICONEXCLAMATION);
}

GetDlgItem(IDC_BTNCAPTURE2)->EnableWindow(TRUE);
}
this is the code for oncapture

and the thing about
void CPreviewTestDlg::waitPreviewThread(HANDLE * m_hSemaphore);
i declare m_hSemaphore as pointer variable and pass the address of the m_hSem

regards
mohamed

Siddhartha
September 6th, 2005, 05:19 AM
[ code tags added ]

Regards,
Siddhartha

PS: Please post your code using Code Tags. Thank you.

Siddhartha
September 6th, 2005, 05:39 AM
Okay, answering the smaller questions before I get to the big-picture...
My question isnt it allowed to access or waitforsingleobject twice ?It is... You can call WaitForSingleObject as often as you like - so long as you have a valid HANDLE to wait on.
And why does it work when i use a messagebox , does messagebox clear something or does it give a delay ? Then why doesnt Sleep workThread behaviour is transient... Without seeing all the code, one cant say for sure.

What I can tell is that there is no direct connection between MessageBox and the Wait Functions or Semaphore.

Coming to the Semaphore creation code...
// create a semaphore object to syncronize the preview thread
// with the main thread so we don't try to access the camera
// from two threads at the same time
m_hSem = CreateSemaphore(NULL, 1, 1, NULL); You are creating a Semaphore with a count of 1.

This means that you only need a system that allows one thread to access a section of code at a time, am I right in my understanding?

If so, Semaphores are not the right objects for you... One would typically use Semaphore to ensure that a section of code is entered by N threads at a time. (N = 1) is sub-optimal.

CRITICAL SECTIONS (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/critical_section_objects.asp) are made for this. They are simple to use, and ensure that a piece of code is accessed one thread at a time.

When you answer the question above, I'll detail on using CRITICAL SECTIONS if need be.

mohamed123
September 6th, 2005, 06:39 AM
hi
your replies helped me understanding the semaphore better thanx

time line goes like this

OnCapture
- waitforsingleobject this would stop the preview thread
- capture - contacts camera and takes pic , when preview is paused
- releasesemaphore , starts the preview thread again

i do the same again

OnCapture
- waitforsingleobject this would stop the preview thread
- capture - contacts camera and takes pic , when preview is paused
- releasesemaphore , starts the preview thread again


but what happens is the second time during wait for single object the , wait is not returning

i have attached code as file for your reference

regards
mohamed

Siddhartha
September 6th, 2005, 07:45 AM
your replies helped me understanding the semaphore better thanxYou are welcome... :)

but what happens is the second time during wait for single object the , wait is not returningThis can happen only when you have taken a Semaphore (i.e. Waited on it...) but not released it later. So, the Semaphore remains non-Signaled, and all further waits on it are blocked.

Hence, please check all your code flows for this situation.

Now, I need a clarification - Initially you said that the WaitForSingleObject crashed on the second call.
Does it crash no more?

Remember that for WaitForSingleObject to work fine, the HANDLE to the semaphore m_hSem should be valid.

But, if you do a CloseHandle as in here -
void CPreviewTestDlg::OnPreview ()
{
// [...]
CloseHandle(m_hSem2);
} ...before calling WaitForSingleObject the second time, remember that you have sent an invalid HANDLE, and strange behaviour is to be expected.

You are also Closing the Handle in OnPreview2().

Use breakpoints to make sure that the HANDLE is not being closed before you use it again. i have attached code as file for your reference Yes, I looked into it... I see that you need to stop one thread, start another, etc - and whilst CRITICAL SECTIONS are not applicable - Events, IMO would be better suited.

There is only so much one can say / do without being able to debug... ;)

mohamed123
September 6th, 2005, 07:57 AM
hi

This can happen only when you have taken a Semaphore (i.e. Waited on it...) but not released it later. So, the Semaphore remains non-Signaled, and all further waits on it are blocked.

Hence, please check all your code flows for this situation.

Now, I need a clarification - Initially you said that the WaitForSingleObject crashed on the second call.
Does it crash no more?

Remember that for WaitForSingleObject to work fine, the HANDLE to the semaphore m_hSem should be valid.

the handle seems to be ok since i checked while debug and found the same address value as in first call . ( 0x00000b14 )

the it does return !!!

regards
mohamed

Siddhartha
September 6th, 2005, 08:00 AM
Please use Code-Tags, and please use Quote-Tags.
I don't relish the idea of doing this for you - for every post of yours... ;)
the handle seems to be ok since i checked while debug and found the same address value as in first call . ( 0x00000b14 ) You see, CloseHandle does not change the value of the handle... You can invalidate the HANDLE by calling CloseHandle (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/closehandle.asp) on it, and continue to use the same...

mohamed123
September 6th, 2005, 08:06 AM
hi

i dont closehandle any where during the process i check that and
when reduced the timeout time for waitforsingleobject
, it retunrs and says " Camera timed out"

does that mean the camera is not responding to second capture call ???

regards
mohamed

mohamed123
September 6th, 2005, 08:10 AM
but if use a messagebox inbetween


if (m_pThread)
{
MessageBox("test",NULL,MB_OK);
dwRes = WaitForSingleObject(m_hSem,10000);
}


works fine !!!!

Siddhartha
September 6th, 2005, 08:14 AM
i dont closehandle any where during the process i check that and
when reduced the timeout time for waitforsingleobject
, it retunrs and says " Camera timed out"

does that mean the camera is not responding to second capture call ???As neither your exe, nor your camera and your environment are in my posession - I am not in a position to hazard a guess.

What I can tell you is that you need a ReleaseSemaphore for every WaitForSingleObject, and if you timeout - I think, you still need to do a ReleaseSemaphore - something you are not doing.

Else, your Semaphore remains non-signaled forever... And subsequent waits will not return.

mohamed123
September 6th, 2005, 09:14 AM
hi
i just addedone more releasesemaphhore

between oncapture and oncapture2

and it worked

i think what u said about releasesemaphore was right

although i use releasesemaphore immly in oncapture

next time when i call oncapture the waitforsingleobject doesnt return strange!!!

but when i releasesemaphore in

CaptureAll()
{
OnCapture();
ReleaseSemaphore(m_hSem, 1, NULL);
OnCapture();
}

works perfectly

any it works

thanx for you guidance

regards
mohamed

Siddhartha
September 6th, 2005, 09:21 AM
thanx for you guidance You are welcome... :)

BTW, a correct place for the ReleaseSemaphore might be here inside OnCapture -
if (dwRes == WAIT_TIMEOUT)
{
AfxMessageBox(_T("Camera timed out."), MB_OK);
ReleaseSemaphore (m_hSem);
return;
} Before the return.

Test it out...