Opened 14 years ago
Closed 14 years ago
#2854 closed Bugs (invalid)
Boost assertion fails inconsistently
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | Boost 1.39.0 | Component: | regex |
Version: | Boost 1.35.0 | Severity: | Problem |
Keywords: | Cc: |
Description
I have a code that matches URI with a pattern using regex_match. This code fails sometimes, mostly when a lot of threads (50 and above) call this function simultaneously. I have read the boost:regex is thread-safe. Here is the stack
[1] lwp_kill(0x0, 0x6, 0x0, 0x6, 0xffbffeff, 0x0), at 0xff0caa58
[2] raise(0x6, 0x0, 0x0, 0x6, 0x82bf8, 0x6), at 0xff065a5c [3] abort(0xf88f9e78, 0x2, 0x0, 0xfcb78, 0xff1413d8, 0x1), at 0xff04194c [4] assert(0x1f7544, 0x1f7557, 0x1ed, 0x1c00, 0xfc894, 0x1b41ac), at 0xff041b88 [5] boost::basic_regex<char,boost::regex_traits<char,boost::cpp_regex_traits<char> > >::get_traits(0x4e4130, 0xffff0000, 0x0, 0x1f75ed, 0x0, 0x1f7400), at 0xc77e0 [6] boost::regex_match<const char*,std::allocator<boost::sub_match<const char*> >,char,boost::regex_traits<char,boost::cpp_regex_traits<char> > >(0x2212e30, 0x2212e6e, 0xf88fa368, 0x4e4130, 0x0, 0x7ffffc00), at 0xc7664 [7] URL::parseUrl(0xf88fa4cc, 0x1fc21c, 0x2212e30, 0x56e500, 0xf88fa4d0, 0xf88fa368), at 0xcef5c Thanks Dinesh
Change History (3)
comment:1 by , 14 years ago
comment:2 by , 14 years ago
John, Thanks for a promprt response.
void URL::parseUrl() { static const boost::regex e ("^(([^:/?#]+):)?(//)?([^/?#]*)?([^?#]*)(\\?([^#]*))?(#(.*))?"); boost::smatch subMatch; if(regex_match(m_url, subMatch, e)) { ... }
This is where I "usually" get an assertion failure.
Assertion failed: 0 != m_pimpl.get(), file ../../../../3rdpartylibs/boostlibs_1.35boost/regex/v4/basic_regex.hpp, line 493
Thanks for your attention.
Dinesh
comment:3 by , 14 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Hi Dinesh,
there is a race condition in your parseURL function: if two threads enter the function at the same time and the variable e has not yet been initialised then one thread will start initialising the variable, but the other thread may then access it before initialisation is complete.
There are two possible workarounds:
1) Make the regular expression a static data member of the URL class - it will then get initialised at program startup. This is then thread safe provided no threads call URL::parseURL before the start of main(). One other downside is that the regex variable will get initialised whether it is used or not: that's not a problem in this one case, but may be if you have a *lot* of such variables.
2) Use boost::call_once to call an initialisation function function that initialises the regex: this isn't cost free either as call_once has a non-zero overhead.
I'm going to close this issue down for now, but please reopen if you find more problems (or this isn't the solution), or if you need the call_once method explaining in more detail.
Regards, John Maddock.
Dinesh,
There have been quite a few patches between 1.35 and 1.38, can you try your code with the latest Boost release?
It's also hard to get a feel for which assertion is failing from your backtrace as it looks like you have inline expansions turned on? However, it looks like the smart pointer is NULL, which would typically only happen if one thread is modifying the regex object while another thread is using it: Boost.Regex is threadsafe in the sense that if one thread creates a regex then other threads can access that regex as long as they *all* treat it as constant.
HTH, if you have some information let me know, John Maddock.