w00t-labs / libtorrent

Automatically exported from code.google.com/p/libtorrent
Other
0 stars 0 forks source link

Using boost::asio side by side with libtorrent throws access violation exception #716

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
*What steps will reproduce the problem?*

{{{
libtorrent::session s;

boost::asio::io_service io;
boost::asio::ip::tcp::acceptor acceptor(io);
}}}

*What is the expected output? What do you see instead?*

It throws an access violation exception with the following stack trace,

{{{
lt_test.exe!boost::asio::detail::win_iocp_socket_service_base::do_open(boost::as
io::detail::win_iocp_socket_service_base::base_implementation_type & impl, int 
family, int type, int protocol, boost::system::error_code & ec) Line 300    C++
lt_test.exe!boost::asio::detail::win_iocp_socket_service<boost::asio::ip::tcp>::
open(boost::asio::detail::win_iocp_socket_service<boost::asio::ip::tcp>::impleme
ntation_type & impl, const boost::asio::ip::tcp & protocol, 
boost::system::error_code & ec) Line 192   C++
lt_test.exe!boost::asio::socket_acceptor_service<boost::asio::ip::tcp>::open(boo
st::asio::detail::win_iocp_socket_service<boost::asio::ip::tcp>::implementation_
type & impl, const boost::asio::ip::tcp & protocol, boost::system::error_code & 
ec) Line 144   C++
lt_test.exe!boost::asio::basic_socket_acceptor<boost::asio::ip::tcp,boost::asio:
:socket_acceptor_service<boost::asio::ip::tcp> >::open(const 
boost::asio::ip::tcp & protocol, boost::system::error_code & ec) Line 310 C++
lt_test.exe!libtorrent::aux::session_impl::setup_listener(libtorrent::listen_soc
ket_t * s, boost::asio::ip::basic_endpoint<boost::asio::ip::tcp> ep, int & 
retries, bool v6_only, int flags, boost::system::error_code & ec) Line 2089 C++
lt_test.exe!libtorrent::aux::session_impl::open_listen_port(int flags, 
boost::system::error_code & ec) Line 2243   C++
lt_test.exe!libtorrent::aux::session_impl::init() Line 1258    C++
lt_test.exe!libtorrent::aux::session_impl::main_thread() Line 4880 C++
lt_test.exe!boost::_mfi::mf0<void,libtorrent::aux::session_impl>::operator()(lib
torrent::aux::session_impl * p) Line 50    C++
lt_test.exe!boost::_bi::list1<boost::_bi::value<libtorrent::aux::session_impl 
*> 
>::operator()<boost::_mfi::mf0<void,libtorrent::aux::session_impl>,boost::_bi::l
ist0>(boost::_bi::type<void> __formal, 
boost::_mfi::mf0<void,libtorrent::aux::session_impl> & f, boost::_bi::list0 & 
a, int __formal) Line 254    C++
lt_test.exe!boost::_bi::bind_t<void,boost::_mfi::mf0<void,libtorrent::aux::sessi
on_impl>,boost::_bi::list1<boost::_bi::value<libtorrent::aux::session_impl *> > 
>::operator()() Line 21    C++
lt_test.exe!boost::asio::detail::win_thread::func<boost::_bi::bind_t<void,boost:
:_mfi::mf0<void,libtorrent::aux::session_impl>,boost::_bi::list1<boost::_bi::val
ue<libtorrent::aux::session_impl *> > > >::run() Line 117  C++
lt_test.exe!boost::asio::detail::win_thread_function(void * arg) Line 118  C++

}}}

*What version of the product are you using? On what operating system?*

boost 1.57.0, libtorrent 1.0.3 on Windows using MSVC-12.0.

Original issue reported on code.google.com by vik...@viktorelofsson.se on 7 Jan 2015 at 11:35

GoogleCodeExporter commented 8 years ago
Here is a complete example to reproduce the problem on Win 8, MSVC-12.0 with 
the above mentioned Boost and libtorrent versions.

#include <boost/asio.hpp>
#include <libtorrent/session.hpp>

int main(int argc, char *argv[])
{
    boost::asio::io_service io_service;
    boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);

    boost::asio::ip::tcp::acceptor acc(io_service);

    libtorrent::session *s = new libtorrent::session();

    signals.async_wait([](boost::system::error_code error, int signal)
    {

    });

    io_service.run();

    return 0;
}

Original comment by vik...@viktorelofsson.se on 8 Jan 2015 at 7:01

GoogleCodeExporter commented 8 years ago
I wonder if this is because libtorrent exports boost.asio symbols, and if your 
version is different than the one libtorrent built against, there may be ABI 
compatibility issues.

Original comment by arvid.no...@gmail.com on 9 Jan 2015 at 10:05

GoogleCodeExporter commented 8 years ago
I'm building everything from source (static lib). Do you need any more details?

Original comment by vik...@viktorelofsson.se on 10 Jan 2015 at 5:32

GoogleCodeExporter commented 8 years ago
Hi, I've investigated the issue some more and when using shared linking 
everything works as expected. I'm considering this issue resolved.

Original comment by vik...@viktorelofsson.se on 28 Jan 2015 at 1:27

GoogleCodeExporter commented 8 years ago
@arvid,

I'm in need of some help regarding this issue - here's some more detail (still 
MSVC-12 and everything built from source).

I have the following folder structure,

C:\libs\boost (with boost 1.58)
C:\libs\libtorrent (with libtorrent 1.0.5)

---

building libtorrent:

cd C:/libs/libtorrent
..\b2 -sBOOST_ROOT="C:/libs/boost" boost=source

---

building boost:

cd C:/libs/boost
b2 --with-system

---

This successfully compiles and gives me lib files for both Boost and libtorrent.

However, the following sample program fails to run,

#include <libtorrent/session.hpp>

int main(int argc, char *argv[])
{
    boost::asio::io_service io;
    boost::asio::ip::tcp::acceptor server(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 1337));

    libtorrent::session s;
    s.listen_on(std::make_pair(6881, 6889));

    return 0;
}

I know the program does not make any sense, but it demonstrates the issue, and 
fails with the following stack trace: http://pastebin.com/TPT9mt0n

I'm linking the program against the libtorrent.lib file as well as the 
outputted boost system lib file.

You mentioned version diffing, but I can't see it here.

Any advice?

Original comment by vik...@viktorelofsson.se on 3 Jun 2015 at 1:20

GoogleCodeExporter commented 8 years ago
when building libtorrent (with boost=source) libtorrent will simply depend on 
the Jamfiles under $BOOST_ROOT, causing boost-build to build them and link 
against them. If you additionally "link=static" it will link against 
boost.system and boost.asio statically (and build boost-asio with 
separate-compilation set, not headers only).

This causes all of asio symbols and global data to be instantiated inside 
libtorrent.lib (this probably includes asio's service registration and 
boost.system's error categories).

If you then link against your own instance of boost.system and your own version 
of boost.asio (say, by using it as headers only instead of using the symbols 
exported from libtorrent) I imagine you may have two conflicting sets of global 
state.

This being a problem would explain why it works when you link dynamically, 
since then all modules can share a single DLL containing a single instance of 
the global data.

I'm not sure what the best solution to this is though. right now, libtorrent 
"overrides" boost.asio's export macro to make sure it exports its symbols (this 
only applies if libtorrent is built as a DLL btw). libtorrent could use 
boost.asio as header-only. The main reason (iirc) I made it build boost.asio 
was compilation time and to rely less on the linker to merge duplicate code 
(since all of asio will be instantiated in every compilation unit including it).

If you're building libtorrent as a static library too, then I would actually 
expect you to get duplicate definitions at link time.

Maybe you can inspect the resulting executable to see if you have some 
duplicate data symbols.

Original comment by arvid.no...@gmail.com on 3 Jun 2015 at 10:45

GoogleCodeExporter commented 8 years ago
fixed in master

Original comment by arvid.no...@gmail.com on 28 Jul 2015 at 11:05