Weird threading error with LibTiff
-
Hi, I'm using LibTiff to write TIFF files (from multiple threads) in C++, and getting the following error message: "Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TeaxtReader´s or TextWriters´s Synchronized methods. This also applies to classes like StreamWriter and StreamReader" (The C++ is being called from a C# GUI, which accounts for the .NET class names.) The weird thing is that the LibTiff call is in a critical section, which (theoretically) should avoid race conditions:
DLLEXPORT int writeVariableImage (HBITMAP staticBlackLayer, HBITMAP varLayer,
VariableObject* varObj, int numVarObjects,
char* fileName)
{
if (!criticalSectionInitialized)
{
InitializeCriticalSection (&cs);
criticalSectionInitialized = true;
}EnterCriticalSection(&cs); try { // Make copy of black if (!copyBitmap (varLayer, staticBlackLayer)) // layer to mark up: throw 666; // Problem found. HDC memDc = CreateCompatibleDC (NULL); // Prepare to draw: HGDIOBJ Obmp = SelectObject(memDc, varLayer); if (!memDc || !Obmp) throw 666; // Problem found. // Go through objects: for (int i = 0; i < numVarObjects; ++i) // Draw markup: drawVariableObject (memDc, &varObj \[i\]);// Draw next var object. invertLayer (memDc, varLayer); writeToTiffFile (varLayer, fileName); // Write to file. if (!SelectObject (memDc, Obmp) || // Clean up: !DeleteDC (memDc)) throw 666; // Problem found. } catch (...) { DWORD err = GetLastError (); if (err) { LPTSTR s; // Show error message: FormatMessage(FORMAT\_MESSAGE\_ALLOCATE\_BUFFER | FORMAT\_MESSAGE\_FROM\_SYSTEM, NULL, err, 0, (LPTSTR)&s, 0, NULL); MessageBox (NULL, s, L"Error", 0); LocalFree (s); } LeaveCriticalSection(&cs); return 0; // Failed. } LeaveCriticalSection(&cs); return 1; // Success.
}
The other oddity is that the error only shows up on 1 out of the 4 computers it's been tried on. (The computer that shows the error has 4 cores, the others, 2.) Any ideas what could be causing this, or how to avoid it? Thanks!
-
Hi, I'm using LibTiff to write TIFF files (from multiple threads) in C++, and getting the following error message: "Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TeaxtReader´s or TextWriters´s Synchronized methods. This also applies to classes like StreamWriter and StreamReader" (The C++ is being called from a C# GUI, which accounts for the .NET class names.) The weird thing is that the LibTiff call is in a critical section, which (theoretically) should avoid race conditions:
DLLEXPORT int writeVariableImage (HBITMAP staticBlackLayer, HBITMAP varLayer,
VariableObject* varObj, int numVarObjects,
char* fileName)
{
if (!criticalSectionInitialized)
{
InitializeCriticalSection (&cs);
criticalSectionInitialized = true;
}EnterCriticalSection(&cs); try { // Make copy of black if (!copyBitmap (varLayer, staticBlackLayer)) // layer to mark up: throw 666; // Problem found. HDC memDc = CreateCompatibleDC (NULL); // Prepare to draw: HGDIOBJ Obmp = SelectObject(memDc, varLayer); if (!memDc || !Obmp) throw 666; // Problem found. // Go through objects: for (int i = 0; i < numVarObjects; ++i) // Draw markup: drawVariableObject (memDc, &varObj \[i\]);// Draw next var object. invertLayer (memDc, varLayer); writeToTiffFile (varLayer, fileName); // Write to file. if (!SelectObject (memDc, Obmp) || // Clean up: !DeleteDC (memDc)) throw 666; // Problem found. } catch (...) { DWORD err = GetLastError (); if (err) { LPTSTR s; // Show error message: FormatMessage(FORMAT\_MESSAGE\_ALLOCATE\_BUFFER | FORMAT\_MESSAGE\_FROM\_SYSTEM, NULL, err, 0, (LPTSTR)&s, 0, NULL); MessageBox (NULL, s, L"Error", 0); LocalFree (s); } LeaveCriticalSection(&cs); return 0; // Failed. } LeaveCriticalSection(&cs); return 1; // Success.
}
The other oddity is that the error only shows up on 1 out of the 4 computers it's been tried on. (The computer that shows the error has 4 cores, the others, 2.) Any ideas what could be causing this, or how to avoid it? Thanks!
Some ideas to help you track down problem. 1. You seem to have the 'source code'. I would move the critical section initialization outside this function and make damn sure it is already done before ANY thead has a achance to call the function. 2. Make sure no two calls are trying to write to the same file. 3. Increment a local variable along the way - print out its value in the exception handler to get an idea WHERE you had a problem. They currently thow 666 everywhere - not too easy to tell what the real problem is when that is being done. I would not try too hard to figure out what is wrong without the changes I suggest above, which is what I would do to allow me to diagnose the actual problem.
-
Some ideas to help you track down problem. 1. You seem to have the 'source code'. I would move the critical section initialization outside this function and make damn sure it is already done before ANY thead has a achance to call the function. 2. Make sure no two calls are trying to write to the same file. 3. Increment a local variable along the way - print out its value in the exception handler to get an idea WHERE you had a problem. They currently thow 666 everywhere - not too easy to tell what the real problem is when that is being done. I would not try too hard to figure out what is wrong without the changes I suggest above, which is what I would do to allow me to diagnose the actual problem.
Great suggestions! Thanks! (I especially like #1; multiple threads could hit this at once.)