I'm running into an odd deadlock situation, and I was wondering if it's a
known issue, or if there's likely something wrong with my code, or if I've
misconfigured something? First off, a stack trace:
ntdll.dll!77f5b7f4()
kernel32.dll!77e61bf5()
scanner.exe!boost::detail::sp_counted_base::release() Line 132 + 0xf C++
scanner.exe!boost::detail::shared_count::~shared_count() Line 380 C++
scanner.exe!boost::shared_ptr
Ken Alverson wrote:
I'm running into an odd deadlock situation, and I was wondering if it's a known issue, or if there's likely something wrong with my code, or if I've misconfigured something? First off, a stack trace:
ntdll.dll!77f5b7f4() kernel32.dll!77e61bf5() scanner.exe!boost::detail::sp_counted_base::release() Line 132 + 0xf C++
Is it possible that your program is using the multithreaded runtime but the filesystem library has been compiled as single threaded, or vice versa?
Peter Dimov wrote:
Is it possible that your program is using the multithreaded runtime but the filesystem library has been compiled as single threaded, or vice versa?
Certainly with Borland win32 builds, all libraries (bar thread obviously) default to single threaded. I've had to build all libraries as the multi-threaded version. Dead-lock was the result I saw because of waiting on the spin-lock in a shared_ptr (app was multi-threaded, signals library was single threaded in my case) Cheers Russell
Russell Hind wrote:
Peter Dimov wrote:
Is it possible that your program is using the multithreaded runtime but the filesystem library has been compiled as single threaded, or vice versa?
Certainly with Borland win32 builds, all libraries (bar thread obviously) default to single threaded. I've had to build all libraries as the multi-threaded version.
Dead-lock was the result I saw because of waiting on the spin-lock in a shared_ptr (app was multi-threaded, signals library was single threaded in my case)
This proved to be a common problem with the 1.30.0 release as now more libraries require a build step. I've now updated shared_ptr in the CVS to be binary compatible on Win32 regardless of the threading settings used.
"Peter Dimov"
Ken Alverson wrote:
I'm running into an odd deadlock situation, and I was wondering if it's a known issue, or if there's likely something wrong with my code, or if I've misconfigured something? First off, a stack trace:
ntdll.dll!77f5b7f4() kernel32.dll!77e61bf5() scanner.exe!boost::detail::sp_counted_base::release() Line 132 + 0xf C++
Is it possible that your program is using the multithreaded runtime but the filesystem library has been compiled as single threaded, or vice versa?
Certainly a possibility...this is the first time I've tried using a non header-based boost component. However, I thought the boost config defaulted to thread support. I certainly didn't do anything special to enable multithreading support on boost. (and my application is statically linked to the multithreaded runtime) Is there a document somewhere describing how to select which runtime boost will be built against? Ken
When you build, I use (for borland) bjam -sTOOLS="borland" -sBUILD="<threading>multi" or something like that, haven't done it since the 1.30.0 release. It definitely defaults to single threaded for borland for all libraries bar boost::thread I like the regex way of building and plan to introduce my own here so that I append mt/st to the .lib file name and link against the correct version with #pragma statements. The other problem I've found (and we discussed before) was the build settings (alignment etc). boost has default settings for all compilers and these may be different from your project options. (we tend to build with 4-byte alignment rather than 8 but boost defaults to 8). This also causes problems because of inlined code/.lib code in the same project. I've wrapped all the boost headers (that I use) in a directory called boost_wrappers that first include a push header file to push all the boost options for the compiler, then include the boost header, then a pop header to pop the options back to the correct project settings. We did discuss a while back about getting these push pragmas at the start and end of each header but there doesn't seem to be much support for it. Without it, or without doing your own (as I have) you can't change or project options (or some of them) without re-building boost with those same options which is a PITA. As an extra, I've built both debug and non-debug versions and appended a d to the debug files so I can #define DEBUG_BOOST_XXXXX to link with the debug version of the library and step through the code which can be quite handy. Cheers Russell Ken Alverson wrote:
Certainly a possibility...this is the first time I've tried using a non header-based boost component. However, I thought the boost config defaulted to thread support. I certainly didn't do anything special to enable multithreading support on boost. (and my application is statically linked to the multithreaded runtime)
Is there a document somewhere describing how to select which runtime boost will be built against?
Ken
"Russell Hind"
When you build, I use (for borland)
bjam -sTOOLS="borland" -sBUILD="<threading>multi"
or something like that, haven't done it since the 1.30.0 release. It definitely defaults to single threaded for borland for all libraries bar boost::thread
Thanks, it took a couple tries and a few reads through the bjam documentation before it clicked, but it seems to be working now (though I get a couple build errors, mostly on the test directories). I ended up with: bjam -sTOOLS="vc7" -sBUILD="debug release <runtime-link>static <threading>multi" I have one final question. I am using the threading dll, statically linked with the multithreaded runtime. My program (and the boost filesystem lib, which I statically link against) is also statically linked with the multithreaded runtime. This means there are two instances of the static runtime, one shared by my program and the filesystem, and one used by the threading library. Now, I know there are perils to having more than one copy of the runtime - notably if memory allocated in one runtime is freed by a different runtime. My question is whether it is safe to use the threading library linked in this way. I can't link against the dynamic runtime because I have to assume it is not present, but I can't link the threading library statically since it isn't designed to be built statically. If not, is there a preferred solution? Ken
Ken Alverson wrote:
I have one final question. I am using the threading dll, statically linked with the multithreaded runtime. My program (and the boost filesystem lib, which I statically link against) is also statically linked with the multithreaded runtime. This means there are two instances of the static runtime, one shared by my program and the filesystem, and one used by the threading library.
I'm unsure how this would behave. I have built the thread library as a lib for now (inspite of the problems when doing this).
Now, I know there are perils to having more than one copy of the runtime - notably if memory allocated in one runtime is freed by a different runtime. My question is whether it is safe to use the threading library linked in this way. I can't link against the dynamic runtime because I have to assume it is not present, but I can't link the threading library statically since it isn't designed to be built statically.
Could you do what regex has done, and build another version of the thread dll (which uses the dynamic RTL) and use #praga link statements in your code to decide which .lib to link against for the dll? Regex builds multiple libraries with different letters appended to the names for debug, release, single-threaded, multi-threaded etc, then there is a header file that picks out the correct by checking compiler settings, and inserts a #pragma link statement in the code to force the linker to look for the correct one. Cheers Russell
"Russell Hind"
Could you do what regex has done, and build another version of the thread dll (which uses the dynamic RTL) and use #praga link statements in your code to decide which .lib to link against for the dll?
I'm linking against the correct (static multithreaded) library, the potential problem is that there are two of them (albeit two of the same one). One in the thread dll, one in the exe.
I'm unsure how this would behave. I have built the thread library as a lib for now (inspite of the problems when doing this).
Is there a discussion somewhere on how to do this and what problems (specifically) it can cause? I did a few searches and found lots of talk on why it isn't done, but not specifically what happens if you defy it. Ken
Ken Alverson wrote:
Is there a discussion somewhere on how to do this and what problems (specifically) it can cause? I did a few searches and found lots of talk on why it isn't done, but not specifically what happens if you defy it.
Well, the discussions tell you why it isn't done, so surely that leads you onto what will happen if you use a .lib :) AFAICT, (and this is my basic understanding of the problem) is that using a DLL is the only way to perform cleanup when a thread exits (as the only callback is to the DLLEntryPoint to say a thread has finished). So if you don't run it as a DLL, no clean-up occurs when a thread exits. We only ever create threads at startup and let them exit at shutdown, so I'm willing to risk what leaks could occur due to this. Cheers Russell
Ken Alverson wrote:
"Russell Hind"
wrote in message news:bej3f4$fqg$1@main.gmane.org... I'm linking against the correct (static multithreaded) library, the potential problem is that there are two of them (albeit two of the same one). One in the thread dll, one in the exe.
I understand that, what I'm suggesting is that you can tell if your app is using the dynamic RTL and therefore link against a different version of the thread library that also links against the dynamic rtl. If it isn't using the dynamic rtl, then you have to do what you have done. You'd have to take a closer look at the thread library to see the effect of this, and see where the resources are allocated and released for the objects you are using. AFAICT, all the code for mutexes and threads lives in the thread .cpp src files so hopefully there shouldn't be a problem for these, not sure about other objects. (I use, but haven't had enough of a look at the source for condition) Maybe William can shed more light on this. If the acquisition/releasing of resources is all done in the thread .cpp sources, then there shouldn't be a problem as they will use the RTL linked into the DLL. If any of the code is inlined into headers, then there is a problem. the lock classes are inlined, but they only call method on the mutex which isn't inlined so they shouldn't cause problems. HTH Russell
"Russell Hind"
I understand that, what I'm suggesting is that you can tell if your app is using the dynamic RTL and therefore link against a different version of the thread library that also links against the dynamic rtl.
That would be the preferred solution, if I could assume the presence of the runtime library. However the goal was to eliminate that dependency, since some of the computers it will be running on do not have the dynamic runtime installed. I may end up reverting to that approach and forcing an install of the runtime if it isn't already there. However, I was hoping to avoid that. Ken
participants (3)
-
Ken Alverson
-
Peter Dimov
-
Russell Hind