Boost logo

Boost Users :

Subject: [Boost-users] [Asio] Issues with kqueue_reactor, dynamic libraries and -fvisibility=hidden
From: Andrei Bica (avbica_at_[hidden])
Date: 2013-11-19 08:01:18


I'm having a problem with a larger project for MacOS which uses multiple dynamic libraries and asio features (deadline_timers and tcp/udp scokets).
I've managed to reproduce my problem 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

As you can see 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.

I need an advise on how should I proceed so that I can still use the visibility set to hidden at compilation time but have the example working as expected.

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

Regards,
Andrei


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net