Opened 8 years ago

Closed 8 years ago

#10767 closed Bugs (worksforme)

Regression of #10296 when address-model=32 in mingw

Reported by: Brian Jack <gau_veldt@…> Owned by: Niall Douglas
Milestone: Component: thread
Version: Boost 1.57.0 Severity: Regression
Keywords: Cc:

Description

I have some upstream libraries that will not work in 64-bit build so I had to build boost as a 32-bit target (project-config.jam set to using gcc and build command from the cmd shell is: b2 address-model=32 install).

This all works fine and dandy, except that it causes a regression of the whole #10296 _InterlockedCompareExchange and friends related issues.

You guessed it, it hits the #ifdef(MINGW64_VERSION_MAJOR) defines, finds them defined (we are in address-model=32 remember) and happily creates the underscored forms of the calls in the implementations and the linker happily complains (AGAIN ARGHHHH!) that they are not defined.

Change History (21)

comment:1 by Brian Jack <gau_veldt@…>, 8 years ago

I have some upstream libraries that will not work in 64-bit build so I had to build boost as a 32-bit target (project-config.jam set to using gcc and build command from the cmd shell is: b2 address-model=32 install).

This all works fine and dandy, except that it causes a regression of the whole #10296 _InterlockedCompareExchange and friends related issues.

You guessed it, it hits the ifdef(MINGW64_VERSION_MAJOR) defines, finds them defined (we are in address-model=32 remember) and happily creates the underscored forms of the calls in the implementation blobs and the linker happily complains (AGAIN ARGHHHH!) that they are not defined.

comment:2 by Brian Jack <gau_veldt@…>, 8 years ago

Is there a top level temporary kludge I can use to eliminate this define down the entire build so it'll do the right thing (alias the _Interlocked* forms to the ones without the _)?

comment:3 by Brian Jack <gau_veldt@…>, 8 years ago

as a result of above problem I am unable to use boost.thread in applications using the library without those link errors...

btw my (mingw) gcc is as follows (and being used by my projects in Code::Blocks):

C:\>gcc --version
gcc (tdm64-1) 4.7.1
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

C:\>

the linker has these boost libs being added:

<Add library="libboost_system-mgw47-mt-d-1_57" />
<Add library="libboost_chrono-mgw47-mt-d-1_57" />
<Add library="libboost_date_time-mgw47-mt-d-1_57" />
<Add library="libboost_atomic-mgw47-mt-d-1_57" />
<Add library="libboost_thread-mgw47-mt-d-1_57" />

comment:4 by viboes, 8 years ago

Owner: changed from Anthony Williams to Niall Douglas

Niall?

comment:5 by viboes, 8 years ago

Have you tried to build the whole Boost libraries with

b2 address-model=32 install?

If this is the case and MINGW64_VERSION_MAJOR is defined I don't see what we can do.

comment:6 by Brian Jack <gau_veldt@…>, 8 years ago

yes just to confirm I built the library with: b2 --address-model=32 install

Furthermore the toolchain is set to gcc via project-config.jam

as for workarounds

what about adding a check for this condition (#ifdef MINGW64_VERSION when address-model=32) in the configuration script and define a project-global macro if it is?

Maybe instead of the check itself testing for specific compilers directly in source it tests for a configure script macro that says "don't use intrinsics" instead. then the configuration script and set the build flag appropriately toplevel either in a config header or compilation commandline. In the future the configuration can be changed at one point to set the macro as needed rather than individual source files.

comment:7 by viboes, 8 years ago

Do you know the macro gcc that states that the we are compiling for address-model=32?

comment:8 by Niall Douglas, 8 years ago

I have this Saturday coming available. I will look into it. Note Vicente it is my last available Saturday until after the US Thanksgiving, so I can't look into issues until early December after this weekend.

comment:9 by Brian Jack <gau_veldt@…>, 8 years ago

Alternatively the configurator could also try to build a small intrinsic test program (if boost jam uses test program configure tests) and set a "do not use intrinsics" macro if the link error occurs.

comment:10 by Niall Douglas, 8 years ago

I have been unable to replicate this issue on latest Mingw-w64 (4.9.1) and Boost 1.57:

C:\Users\ned\Documents\boost-release>b2 toolset=gcc address-model=32 --with-thread install -j 4

....

1 file(s) copied.

gcc.compile.c++ bin.v2\libs\thread\build\gcc-mingw-4.9.1\release\address-model-32\link-static\threading-multi\win32\thread.o gcc.archive bin.v2\libs\thread\build\gcc-mingw-4.9.1\release\address-model-32\link-static\threading-multi\libboost_thread-mgw49-mt-1_57.a common.copy C:\Boost\lib\libboost_thread-mgw49-mt-1_57.a bin.v2\libs\thread\build\gcc-mingw-4.9.1\release\address-model-32\link-static\threading-multi\libboost_thread-mgw49-mt-1_57.a

1 file(s) copied.

...updated 3691 targets...

No errors, everything compiled and installed without issue. This was on Win8.1 x86.

Niall

comment:11 by Brian Jack <gau_veldt@…>, 8 years ago

the problem does not happen on build it happens when attempting to link any program using boost.thread

comment:12 by Brian Jack <gau_veldt@…>, 8 years ago

If I comment out test_main and test_thread definitions the project builds and runs. With the two uncommented the errors resulting are posted after the example code.

Test:

#include <windows.h>
#include <iostream>
#include "protocol.hpp"
#include <boost/thread.hpp>

/*
This part is included for reference.
My project builds sucessfully  with this part included
via protocol.cpp/protocol.hpp if test_main and test_thread
definitions are commented out.

Obviously I'm paring this down to the specific problem.

define in protocol.cpp:
boost::mutex cout_mutex;

defined like this protocol.hpp:
class scoped_cout_lock {
    std::ios state;
public:
    scoped_cout_lock() : state(NULL) {
        cout_mutex.lock();
        state.copyfmt(std::cout);
    }
    virtual ~scoped_cout_lock() {
        std::cout.flush();
        std::cout.copyfmt(state);
        cout_mutex.unlock();
    }
};
#define LOCK_COUT {scoped_cout_lock __scl;
#define UNLOCK_COUT }
*/

void test_thread() {
    LOCK_COUT
    std::cout << "Thread 2 says, \"Hello, World!\"" << std::endl;
    UNLOCK_COUT
}

int test_main(int argc,char **argv) {
    boost::thread test(test_thread);
    LOCK_COUT
    std::cout << "Thread 1 says, \"Hello, World!\"" << std::endl;
    UNLOCK_COUT
    test.join();
    return 0;
}

Result:

mingw32-g++.exe -LC:\Minetest-Blockiverse\Minetest-Blockiverse\irrlicht-1.8.1\lib\Win32-gcc -LC:\Boost\lib -L..\zlib125dll\dll32 -L..\OpenAL\libs\Win32 -L..\libvorbis-1.3.4\win32 -L..\libogg-1.3.2\win32\VS2010 -o bin\blockiverse.exe obj\Debug\blockiverse\client.o obj\Debug\blockiverse\main.o obj\Debug\blockiverse\protocol.o obj\Debug\blockiverse\rsa\BigInt.o obj\Debug\blockiverse\rsa\Key.o obj\Debug\blockiverse\rsa\KeyPair.o obj\Debug\blockiverse\rsa\PrimeGenerator.o obj\Debug\blockiverse\rsa\RSA.o obj\Debug\blockiverse\server.o obj\Debug\blockiverse\settings.o obj\Debug\blockiverse\sha1.o -lwsock32 -lws2_32 -lIrrlicht -lopengl32 -lglu32 -lgdi32 -lzlibwapi ..\OpenAL\libs\Win32\OpenAL32.lib -lvorbis -lvorbisfile -logg -lboost_system-mgw47-mt-d-1_57 -lboost_chrono-mgw47-mt-d-1_57 -lboost_date_time-mgw47-mt-d-1_57 -lboost_atomic-mgw47-mt-d-1_57 -lboost_random-mgw47-mt-d-1_57 -lboost_thread-mgw47-mt-d-1_57 C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail5win3223GetTickCount64emulationEv@0': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/thread_primitives.hpp:247: undefined reference to `_InterlockedCompareExchange' C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/thread_primitives.hpp:255: undefined reference to `_InterlockedCompareExchange' C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/thread_primitives.hpp:278: undefined reference to `_InterlockedCompareExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail24interlocked_read_acquireEPVl': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/interlocked_read.hpp:56: undefined reference to `_InterlockedCompareExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail25interlocked_write_releaseEPVll': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/interlocked_read.hpp:64: undefined reference to `_InterlockedExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail21intrusive_ptr_releaseEPNS0_19basic_cv_list_entryE': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/condition_variable.hpp:115: undefined reference to `_InterlockedDecrement' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail17enter_once_regionERNS_9once_flagERNS0_12once_contextE': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/once.hpp:180: undefined reference to `_InterlockedCompareExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail18commit_once_regionERNS_9once_flagERNS0_12once_contextE': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/once.hpp:199: undefined reference to `_InterlockedIncrement' C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/once.hpp:202: undefined reference to `_InterlockedExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost6detail20rollback_once_regionERNS_9once_flagERNS0_12once_contextE': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/once.hpp:215: undefined reference to `_InterlockedExchange' C:\Boost\lib/libboost_thread-mgw47-mt-d-1_57.a(thread.o): In function `ZN5boost9call_onceERNS_9once_flagEPFvvE': C:\Minetest-Blockiverse\Minetest-Blockiverse\boost_1_57_0/./boost/thread/win32/once.hpp:738: undefined reference to `_InterlockedIncrement' collect2.exe: error: ld returned 1 exit status Process terminated with status 1 (0 minute(s), 30 second(s)) 11 error(s), 0 warning(s) (0 minute(s), 30 second(s))

in reply to:  11 comment:13 by Niall Douglas, 8 years ago

Replying to Brian Jack <gau_veldt@…>:

the problem does not happen on build it happens when attempting to link any program using boost.thread

I also compiled and linked and executed a full unit test suite using 32 bit mingw-w64, all of which is dynamically linked to boost.thread. If there were any unresolved symbols, they surely would have appeared then.

Can you provide a small example piece of code which demonstrates this problem please? Posting copy and pastes from a large project we don't have isn't useful. For all we know, this is a bug in GCC 4.7 Mingw's and has since been fixed. This stackoverflow post in fact (https://stackoverflow.com/questions/18134148/undefined-reference-to-interlockedcompareexchange-with-boost-thread-on-mingw64) says this is exactly the problem, and a newer mingw-w64 doesn't have this problem.

Niall

comment:14 by Brian Jack <gau_veldt@…>, 8 years ago

just above your post is a thread-using hello world that does NOT link on my end in GCC 4.7.1 - the commented parts include the code needed to use it without the entire project. failing this I'll jsut stick to CreateThread (sucks as it is makes my code windows-only) as I have been doing since boost::thread right now is the only thing not working in the project as a whole and it's beyond me to fix this on my installation (a newer MINGW is A LOT of work on 64-bit Windows system to install particualrly over an older mingw).

comment:15 by Brian Jack <gau_veldt@…>, 8 years ago

I should point out the stack overflow question refers to a cross-compiling situation also.

comment:16 by viboes, 8 years ago

Any news on this issue?

comment:17 by Niall Douglas, 8 years ago

The hello world example he posted appears to still rely on external files. I reduced that to:

#include <windows.h>
#include <iostream>
#include <boost/thread.hpp>

boost::mutex cout_mutex;

class scoped_cout_lock {
    std::ios state;
public:
    scoped_cout_lock() : state(NULL) {
        cout_mutex.lock();
        state.copyfmt(std::cout);
    }
    virtual ~scoped_cout_lock() {
        std::cout.flush();
        std::cout.copyfmt(state);
        cout_mutex.unlock();
    }
};
#define LOCK_COUT {scoped_cout_lock __scl;
#define UNLOCK_COUT }

void test_thread() {
    LOCK_COUT
    std::cout << "Thread 2 says, \"Hello, World!\"" << std::endl;
    UNLOCK_COUT
}

int main(int argc,char **argv) {
    boost::thread test(test_thread);
    LOCK_COUT
    std::cout << "Thread 1 says, \"Hello, World!\"" << std::endl;
    UNLOCK_COUT
    test.join();
    return 0;
}

I ran:

C:\Users\ned\Documents\boost-release>b2 toolset=gcc libs/thread/test//test_10767

Performing configuration checks

    - symlinks supported       : no
    - junctions supported      : yes
    - hardlinks supported      : yes
...patience...
...patience...
...found 1424 targets...
...updating 23 targets...
common.mkdir bin.v2\libs\thread\test\test_10767.test
common.mkdir bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1
common.mkdir bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug
common.mkdir bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug\threa
ding-multi
gcc.compile.c++ bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug\th
reading-multi\test_10767.o
libs\thread\test\test_10767.cpp:29:5: warning: unused parameter 'argc' [-Wunused
-parameter]
 int main(int argc,char **argv) {
     ^
libs\thread\test\test_10767.cpp:29:5: warning: unused parameter 'argv' [-Wunused
-parameter]
gcc.compile.c++ bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug\th
reading-multi\winrt_init.o
gcc.compile.c++ bin.v2\libs\thread\build\gcc-mingw-4.8.1\debug\threading-multi\w
in32\thread.o
gcc.compile.c++ bin.v2\libs\thread\build\gcc-mingw-4.8.1\debug\threading-multi\w
in32\tss_dll.o
gcc.compile.c++ bin.v2\libs\thread\build\gcc-mingw-4.8.1\debug\threading-multi\w
in32\tss_pe.o
gcc.compile.c++ bin.v2\libs\thread\build\gcc-mingw-4.8.1\debug\threading-multi\f
uture.o
gcc.compile.c++ bin.v2\libs\chrono\build\gcc-mingw-4.8.1\debug\threading-multi\c
hrono.o
gcc.compile.c++ bin.v2\libs\chrono\build\gcc-mingw-4.8.1\debug\threading-multi\t
hread_clock.o
gcc.compile.c++ bin.v2\libs\chrono\build\gcc-mingw-4.8.1\debug\threading-multi\p
rocess_cpu_clocks.o
gcc.compile.c++ bin.v2\libs\system\build\gcc-mingw-4.8.1\debug\threading-multi\e
rror_code.o
gcc.link.dll bin.v2\libs\system\build\gcc-mingw-4.8.1\debug\threading-multi\libb
oost_system-mgw48-mt-d-1_57.dll.a
gcc.link.dll bin.v2\libs\chrono\build\gcc-mingw-4.8.1\debug\threading-multi\libb
oost_chrono-mgw48-mt-d-1_57.dll.a
gcc.link.dll bin.v2\libs\thread\build\gcc-mingw-4.8.1\debug\threading-multi\libb
oost_thread-mgw48-mt-d-1_57.dll.a
gcc.link bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug\threading
-multi\test_10767.exe
testing.capture-output bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\d
ebug\threading-multi\test_10767.run
        1 file(s) copied.
**passed** bin.v2\libs\thread\test\test_10767.test\gcc-mingw-4.8.1\debug\threadi
ng-multi\test_10767.test
...updated 23 targets...

Still looks fine to me.

Niall

comment:18 by Brian Jack <gau_veldt@…>, 8 years ago

I've since moved to the bleeding edge (worded as the "convenience version" on C::B site) Code::Blocks (that uses gcc 4.8.1) and this problem no longer occurs. The Code::Block and gcc version changed when I had to switch to on a different machine to continue work on my project.

It would appear thus that this was indeed a gcc 4.7.1 issue.

Same project moved to gcc 4.8.1 now builds properly with boost threads. I've since taken out the windows-only CreateThread workaround (project now uses boost threads) and I regained the platform independence ground I had lost due to the workaround.

comment:19 by viboes, 8 years ago

So, could we close this issue as worksforme?

in reply to:  17 comment:20 by viboes, 8 years ago

Replying to ned14:

The hello world example he posted appears to still rely on external files. I reduced that to: ...

I ran: ...

Still looks fine to me.

Niall

Thanks Niall for this follow up.

comment:21 by viboes, 8 years ago

Milestone: To Be Determined
Resolution: worksforme
Status: newclosed
Note: See TracTickets for help on using tickets.