Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8123659
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T06:14:58+00:00 2026-06-06T06:14:58+00:00

I have a function called PreProcessSource, which allocates a boost::wave::context and does some preprocessing;

  • 0

I have a function called PreProcessSource, which allocates a boost::wave::context and does some preprocessing; nothing fancy at all.

std::string PreProcessSource(const std::string& instring, const std::string& defines)
{
    typedef boost::wave::cpplexer::lex_token<> token_type;
    typedef boost::wave::cpplexer::lex_iterator<token_type> lex_iterator_type;
    typedef boost::wave::context<std::string::iterator, lex_iterator_type> context_type;

    std::string source = instring;
    context_type ctx(source.begin(), source.end()); // DEADLOCK here
    ctx.set_language(boost::wave::enable_emit_line_directives(ctx.get_language(), true));

    if(!defines.empty())
    {
        std::vector<std::string> tokens;
        Split<std::string>(defines, tokens, ",");

        std::vector<std::string>::const_iterator cit = tokens.begin();

        for (;cit != tokens.end(); ++cit)
            ctx.add_macro_definition(*cit);
    }

    context_type::iterator_type first = ctx.begin();
    context_type::iterator_type last = ctx.end();

    std::string outstring;

    while (first != last)
    {
        const token_type::string_type& value = (*first).get_value();
        std::copy(value.begin(), value.end(), std::back_inserter(outstring));
        ++first;
    }

    return outstring;
}

In the past (this project is being modernized so it was broken for a long time) it used to work fine in the same setup:

Library A is a DLL that hosts the PreProcess source function, executable B uses the DLL A and can call PreProcess source, and DLL A can also sometimes call the function itself.

But right now this is no longer the case: whenever DLL A calls the function itself, or DLL A calls another function, which in turn calls back into DLL A PreProcess source, it deadlocks.

Here’s an example that works just fine from my unit testing:

BOOST_AUTO_TEST_CASE(Preprocessor)
{
    std::stringstream sstream;
    sstream << "void main(inout float4 vtxInput : POSITION) { }" << std::endl << std::endl;
    std::string source = sstream.str();
    std::string defines = "";
    try
    {
        std::string shaderCode = Nitro::PreProcessSource(source, defines);
    } catch (boost::wave::preprocess_exception& pe)
    {
        std::cerr << pe.what() << std::endl;
    }
}

And here is the weird bit, if DO_DEADLOCK is defined to 1 in the following piece of code, the deadlock will happen:

class Tutorial00 : public Game
{
public:
    // ...
    Tutorial00()
    : Game()
    {
#if !DO_DEADLOCK
        std::stringstream sstream;
        sstream << "void main(inout float4 vtxInput : POSITION) { }" << std::endl << std::endl;
        std::string source = sstream.str();
        std::string defines = "";
        std::string shaderCode = Nitro::PreProcessSource(source, defines);
#endif
    }

    void LoadContent()
    {
#if DO_DEADLOCK
        std::stringstream sstream;
        sstream << "void main(inout float4 vtxInput : POSITION) { }" << std::endl << std::endl;
        std::string source = sstream.str();
        std::string defines = "";
        std::string shaderCode = Nitro::PreProcessSource(source, defines);
#endif
        // Original code that deadlocks too.
        // Calls in the DLL, which will call PreProcessSource.
        // effect->Initialize(device, source, "DX11");
    }

    // ...
};

#if 1
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
#else
int main(int argc, char* argv[])
#endif
{
    Tutorial00 app;
    app.Run();
    return 0;
}

Note that the constructor is called directly from the executable, whereas LoadContent is called from the DLL:

// In the DLL
void Game::Run()
{
    try
    {
        // ...

        LoadContent();

        // ...
    } catch(/* ... */) { }
}

The code is compiled for x64 and in debug mode.
I compile boost myself into a DLL (using bcp to get the files for the libraries I use) with the following options:

Preprocessor:

  • WIN32
  • BOOST_ALL_NO_LIB
  • BOOST_ALL_DYN_LINK
  • BOOST_THREAD_BUILD_DLL
  • _DLL
  • _DEBUG
  • _WINDOWS
  • _USRDLL

Code Generation:

  • C++ Exceptions (/EHsc)
  • Multi-threaded Debug DLL (/MDd)
  • Function-level linking (/Gy)
  • Streaming SIMD Extensions 2 (/arch:SSE2) (/arch:SSE2)
  • Fast floating point model (/fp:fast)

DLL A uses the same options except for BOOST_ALL_DYN_LINK, BOOST_THREAD_BUILD_DLL and the string pooling option.

The Boost unit test library is build separately as a static library.

Here is the stack trace of the working version:

Nitro.dll!boost::call_once<void (__cdecl*)(void)>(boost::once_flag & flag, void (void)* f)  Line 200    C++
Nitro.dll!boost::call_once(void (void)* func, boost::once_flag & flag)  Line 28 C++
Nitro.dll!boost::spirit::classic::static_<boost::thread_specific_ptr<boost::weak_ptr<boost::spirit::classic::impl::grammar_helper ...  Line 72 + 0x13 bytes C++
Nitro.dll!boost::spirit::classic::impl::get_definition<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 241 + 0x17 bytes   C++
Nitro.dll!boost::spirit::classic::impl::grammar_parser_parse<0,boost::wave::util::time_conversion::time_conversion_grammar, ...  Line 296 + 0xa bytes   C++
Nitro.dll!boost::spirit::classic::grammar<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 55 + 0x3c bytes C++
Nitro.dll!boost::spirit::classic::grammar<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 65 + 0x75 bytes C++
Nitro.dll!boost::spirit::classic::impl::phrase_parser<boost::spirit::classic::space_parser>::parse<char const * __ptr64,boost::wave::util::time_conversion::time_conversion_grammar> ... Line 136   C++
Nitro.dll!boost::spirit::classic::parse<char const * __ptr64,boost::wave::util::time_conversion::time_conversion_grammar, ... Line 155 + 0x3a bytes C++
Nitro.dll!boost::spirit::classic::parse<char,boost::wave::util::time_conversion::time_conversion_grammar, ... Line 173 + 0x23 bytes C++
Nitro.dll!boost::wave::util::time_conversion::time_conversion_helper::time_conversion_helper(const char * act_time)  Line 123   C++
Nitro.dll!boost::wave::util::predefined_macros::predefined_macros()  Line 196 + 0x38 bytes  C++
...
Nitro.dll!Nitro::PreProcessSource(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & instring, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & defines)  Line 51 + 0xa0 bytes    C++
NitroCoreUnitTests.exe!Preprocessor::test_method()  Line 16 C++
NitroCoreUnitTests.exe!Preprocessor_invoker()  Line 7 + 0x1f bytes  C++
...
NitroCoreUnitTests.exe!boost::unit_test::unit_test_main(boost::unit_test::test_suite * (int, char * *)* init_func, int argc, char * * argv)  Line 187   C++
NitroCoreUnitTests.exe!main(int argc, char * * argv)  Line 238  C++
NitroCoreUnitTests.exe!__tmainCRTStartup()  Line 555 + 0x19 bytes   C
NitroCoreUnitTests.exe!mainCRTStartup()  Line 371   C
kernel32.dll!00000000766a652d()     
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
ntdll.dll!0000000076d9c521()    

And here is the stack trace of the deadlock:

ntdll.dll!0000000076dc135a()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
KernelBase.dll!000007fefd4f10dc()   
Nitro.dll!boost::call_once<void (__cdecl*)(void)>(boost::once_flag & flag, void (void)* f)  Line 197 + 0x18 bytes   C++
Nitro.dll!boost::call_once(void (void)* func, boost::once_flag & flag)  Line 28 C++
Nitro.dll!boost::spirit::classic::static_<boost::thread_specific_ptr<boost::weak_ptr<boost::spirit::classic::impl::grammar_helper ...  Line 72 + 0x13 bytes C++
Nitro.dll!boost::spirit::classic::impl::get_definition<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 241 + 0x17 bytes   C++
Nitro.dll!boost::spirit::classic::impl::grammar_parser_parse<0,boost::wave::util::time_conversion::time_conversion_grammar, ...  Line 296 + 0xa bytes   C++
Nitro.dll!boost::spirit::classic::grammar<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 55 + 0x3c bytes C++
Nitro.dll!boost::spirit::classic::grammar<boost::wave::util::time_conversion::time_conversion_grammar, ... Line 65 + 0x75 bytes C++
Nitro.dll!boost::spirit::classic::impl::phrase_parser<boost::spirit::classic::space_parser>::parse<char const * __ptr64,boost::wave::util::time_conversion::time_conversion_grammar> ... Line 136   C++
Nitro.dll!boost::spirit::classic::parse<char const * __ptr64,boost::wave::util::time_conversion::time_conversion_grammar, ... Line 155 + 0x3a bytes C++
Nitro.dll!boost::spirit::classic::parse<char,boost::wave::util::time_conversion::time_conversion_grammar, ... Line 173 + 0x23 bytes C++
Nitro.dll!boost::wave::util::time_conversion::time_conversion_helper::time_conversion_helper(const char * act_time)  Line 123   C++
Nitro.dll!boost::wave::util::predefined_macros::predefined_macros()  Line 196 + 0x38 bytes  C++
...
Nitro.dll!Nitro::PreProcessSource(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & instring, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & defines)  Line 51 + 0xa0 bytes    C++
Tutorial01.exe!Tutorial01::LoadContent()  Line 70 + 0x33 bytes  C++
Nitro.dll!Nitro::Game::Run()  Line 40   C++
Tutorial01.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow)  Line 149  C++
Tutorial01.exe!__tmainCRTStartup()  Line 547 + 0x42 bytes   C
Tutorial01.exe!wWinMainCRTStartup()  Line 371   C
kernel32.dll!00000000766a652d()     
ntdll.dll!0000000076d9c521()    

It seems boost::wave is trying to parse some time stamp, and by doing so instantiates a grammar and that’s when things seem to go South.

Thanks in advance for any help 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T06:14:59+00:00Added an answer on June 6, 2026 at 6:14 am

    I found the following ticket opened on boost’s trac: boost::call_once not re-entrant (at least in win32)

    It says that call_once is not re-entrant, and shouldn’t be called recursively. Thus the code that I am employing is undefined behavior; the ticket was marked as “will not fix”.

    The solution I’ve taken was to create a separate DLL that only contains the PreProcessSource function.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a function called goRight() which does some stuff when I click a
Let's say I have a function called DisplayWhiskers() which puts some slashes and backslashes
Let's say I have a function called MyFunction(int myArray[][]) that does some array manipulations.
Now I'm sure this is super easy, I have a function called remove_deposit which
hi i have function which is called by tinker listbox so i cannot return
I have three classes that all have a static function called 'create'. I would
I have a function which calculates distance from database records. This function is called
I have a function called block which simply return false; this is meant to
If I have a function called from a few places, and it requires some
I have a function called listelements() , which outputs text like <li>text1</li><li>text2</li> . I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.