In Delphi, is OutputDebugString thread safe? In Delphi, is OutputDebugString thread safe? multithreading multithreading

In Delphi, is OutputDebugString thread safe?


Well, not that it isn't true, it is, but just so that you don't have to just take Lieven word for it:

Passing of data between the application and the debugger is done via a 4kbyte chunk of shared memory, with a Mutex and two Event objects protecting access to it. These are the four kernel objects involved.

Understanding Win32 OutputDebugString is an excellent article on the matter.


Don't worry, it is.

When OutputDebugString() is called by an application, it takes these steps. Note that a failure at any point abandons the whole thing and treats the debugging request as a no-op (the string isn't sent anywhere).

  1. Open DBWinMutex and wait until we have exclusive access to it.
  2. Map the DBWIN_BUFFER segment into memory: if it's not found, there is no debugger running so the entire request is ignored.
  3. Open the DBWIN_BUFFER_READY and DBWIN_DATA_READY events. As with the shared memory segment, missing objects mean that no debugger is available.
  4. Wait for the DBWIN_BUFFER_READY event to be signaled: this says that the memory buffer is no longer in use. Most of the time, this event will be signaled immediately when it's examined, but it won't wait longer than 10 seconds for the buffer to become ready (a timeout abandons the request).
  5. Copy up to about 4kbytes of data to the memory buffer, and store the current process ID there as well. Always put a NUL byte at the end of the string.
  6. Tell the debugger that the buffer is ready by setting the DBWIN_DATA_READY event. The debugger takes it from there.
  7. Release the mutex
  8. Close the Event and Section objects, though we keep the handle to the mutex around for later.


I've had trouble once, though, with strings in an ISAPI DLL. For some odd reason the IsMultiThread boolean defined in System.pas was not set!

It was causing weird AccessViolations, once the thread was running more than one thread... A simple "IsMultiThread:=true;" in a unit initialization fixed it.