Opened 5 years ago

#9465 new Bugs

Issues with kqueue_reactor, dynamic libraries and -fvisibility=hidden

Reported by: avbica@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.54.0 Severity: Problem
Keywords: kqueu_reactor visibility hidden Cc:

Description

I've discovered a problem within a larger project for MacOS which uses multiple dynamic libraries and asio features (deadline_timers and tcp/udp sockets).

After investigating the problem I've managed to reproduce it in the following minimal example:

////////// Timer.hpp ////////// 

#ifndef TIMER_HPP 
#define TIMER_HPP 

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 

#define VISIBLE __attribute__ ((visibility ("default"))) 

class VISIBLE Timer { 
  public: 
    Timer(boost::asio::io_service& service); 
  private: 
    void onTimeout(const boost::system::error_code& code); 
    boost::asio::deadline_timer timer; 
}; 
#endif // Timer_HPP 


////////// Timer.cpp ////////// 

#include <Timer.hpp> 

Timer::Timer(boost::asio::io_service& service) : timer(service) { 
  timer.expires_from_now(boost::posix_time::seconds(1)); 
  timer.async_wait(boost::bind(&Timer::onTimeout, this, _1)); 
} 

void Timer::onTimeout(const boost::system::error_code& code) { 
  std::cout << "The callback from the dynamic library was called." << std::endl; 
} 


////////// main.cpp ////////// 

#include <Timer.hpp> 

boost::asio::io_service service; 

void run() { 
  service.run(); 
} 

void onTimeout(const boost::system::error_code& code) { 
  std::cout << "The callback from main was called." << std::endl; 
} 

int main() { 
  Timer timer(service); 
  boost::asio::deadline_timer deadline_timer(service); 
  deadline_timer.expires_from_now(boost::posix_time::seconds(1)); 
  deadline_timer.async_wait(boost::bind(&onTimeout, _1)); 
  boost::thread t(boost::bind(&run)); 
  t.join(); 
  return 0; 
} 

Timer.cpp is compiled into a dynamic library and used by main.cpp which is compiled as an executable. The environment: MacOS 10.8.5, Boost 1.54.0, clang 500.2.79

The parameters which are passed to clang at compilation time are:

clang++ -ggdb -c Timer.cpp -I. -I/opt/local/include -fPIC -fvisibility=hidden

clang++ -ggdb -o libTimer.dylib -dynamiclib Timer.o -L/opt/local/lib -lboost_thread-mt -lboost_system-mt -fvisibility=hidden

clang++ -ggdb main.cpp -o runTest -I. -I/opt/local/include -L. -L/opt/local/lib -lboost_thread-mt -lboost_system-mt -lTimer fvisibility=hidden

The visibility is set to hidden at compilation time in order to expose only desired functions (e.g. the Timer class) from my library. The problem that arise is that the callback of the timer from main.cpp is never called. If I remove the visibility flag at compilation time the example works as it should (both timer callbacks are called).

When I did further investigations I've observed that 2 kqueue_reactor instances are create when using hidden visibility and only one kqueue_reactor is created when visibility is set to default.

When compiling the example on Linux using visibility set to hidden the example works as expected.

Change History (0)

Note: See TracTickets for help on using tickets.