Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSRM Route crash #4515

Closed
AlekseiSolonkov opened this issue Sep 18, 2017 · 10 comments
Closed

OSRM Route crash #4515

AlekseiSolonkov opened this issue Sep 18, 2017 · 10 comments

Comments

@AlekseiSolonkov
Copy link

AlekseiSolonkov commented Sep 18, 2017

OSRM version 5.12

(gdb) backtrace
#0  0x00007ff17a7a4441 in QSqlDatabase::close() () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#1  0x00007ff17a7a6ab9 in QSqlDatabase::~QSqlDatabase() () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#2  0x00007ff17a7a97ad in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#3  0x00007ff1784d7019 in QHashData::free_helper(void (*)(QHashData::Node*)) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#4  0x00007ff17a7a4197 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#5  0x00007ff1775762e0 in __run_exit_handlers (status=11, listp=0x7ff1778fd5d8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:83
#6  0x00007ff17757633a in __GI_exit (status=<optimized out>) at exit.c:105
#7  0x00005557b9937233 in signalHandler(int) ()
#8  <signal handler called>
#9  0x00005557b9a43ced in void osrm::engine::routing_algorithms::annotatePath<osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> >(osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> const&, osrm::engine::PhantomNodes const&, std::vector<unsigned int, std::allocator<unsigned int> > const&, std::vector<unsigned int, std::allocator<unsigned int> > const&, std::vector<osrm::engine::PathData, std::allocator<osrm::engine::PathData> >&) ()
#10 0x00005557b9a5c4c7 in osrm::engine::InternalRouteResult osrm::engine::routing_algorithms::directShortestPathSearch<osrm::engine::routing_algorithms::ch::Algorithm>(osrm::engine::SearchEngineData<osrm::engine::routing_algorithms::ch::Algorithm>&, osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> const&, osrm::engine::PhantomNodes const&) ()
#11 0x00005557b99ce76b in osrm::engine::RoutingAlgorithms<osrm::engine::routing_algorithms::ch::Algorithm>::DirectShortestPathSearch(osrm::engine::PhantomNodes const&) const ()
#12 0x00005557b9a3f615 in osrm::engine::plugins::ViaRoutePlugin::HandleRequest(osrm::engine::RoutingAlgorithmsInterface const&, osrm::engine::api::RouteParameters const&, osrm::util::json::Object&) const ()
#13 0x00005557b99dcef6 in osrm::engine::Engine<osrm::engine::routing_algorithms::ch::Algorithm>::Route(osrm::engine::api::RouteParameters const&, osrm::util::json::Object&) const ()
#14 0x00005557b9939bf9 in main::{lambda(std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>)#7}::operator()(std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>) const::{lambda(int, std::vector<Point, std::allocator<std::vector> >&, bool)#1}::operator()(int, std::vector<Point, std::allocator<std::vector> >, bool) const ()
#15 0x00005557b9949dfa in main::{lambda(std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>)#7}::operator()(std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>) const ()
#16 0x00005557b994dee4 in std::_Function_handler<void (std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>), main::{lambda(std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>)#7}>::_M_invoke(std::_Any_data const&, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>&&, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>&&) ()
#17 0x00005557b9991307 in SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::write_response(std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > const&, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request> const&, std::function<void (std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Response>, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request>)>&) ()
#18 0x00005557b99a720a in SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::find_resource(std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > const&, std::shared_ptr<SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::Request> const&) ()
#19 0x00005557b99a7dc9 in SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::read_request_and_content(std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > const&)::{lambda(boost::system::error_code const&, unsigned long)#1}::operator()(boost::system::error_code const&, unsigned long) const ()
#20 0x00005557b99a8113 in boost::asio::detail::read_until_delim_string_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, std::allocator<char>, SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::read_request_and_content(std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > const&)::{lambda(boost::system::error_code const&, unsigned long)#1}>::operator()(boost::system::error_code const&, unsigned long, int) ()
#21 0x00005557b99a93dd in boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, boost::asio::detail::read_until_delim_string_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, std::allocator<char>, SimpleWeb::ServerBase<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >::read_request_and_content(std::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > const&)::{lambda(boost::system::error_code const&, unsigned long)#1}> >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) ()
#22 0x00005557b99381f5 in boost::asio::io_service::run() [clone .isra.1139] ()
#23 0x00007ff177ede50f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#24 0x00007ff1781b26ca in start_thread (arg=0x7ff134ff9700) at pthread_create.c:333
#25 0x00007ff177644caf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:105
@danpat
Copy link
Member

danpat commented Sep 18, 2017

@AlekseiSolonkov Please supply more information. It looks like you're using libosrm inside some custom application - how are you calling OSRM code? What parameters are you supplying?

Without more information to reproduce the issue, we cannot fix this.

@AlekseiSolonkov
Copy link
Author

AlekseiSolonkov commented Sep 18, 2017

I use the traffic extension to set the speeds (data I get from the gps-trackers). Also, I change the car.lua profile to allow/disable travel on toll roads. There is an assumption that sometimes when it is impossible to build a road graph the library flies out.
Part of the code to call (run in multithread):

server.resource["^/route([[:print:]]+)$"]["GET"]=[&server,&traffic,&bridges,&request_id,&toll_roads,&lg](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
    try {
      auto t1 = std::chrono::system_clock::now();
      std::atomic_fetch_add(&request_id, ULLINT(1));
      bool is_array = false;
      string param_name, param_value, method_name, lat_lon, resp_json;
      vector<Point> points;
      map<int, Point> m_points;
      string s = request->path;
      s = url_decode(s);
      string init_request = s;
      std::smatch m;
      std::regex e("(\\?|\\&)([^=]+)\\=([^&]+)");
      while(std::regex_search(s, m, e))
      {
        int i = 0;
        for (auto x : m)
        {
          string search(x);
          std::size_t found_a = search.find("&");
          std::size_t found_q = search.find("?");
          if (found_a == string::npos && found_q == string::npos)
          {
            if (i++%2)
            {
              param_value = x;
              if (param_name.find("loc[") != string::npos)
              {
                is_array = true;
                lat_lon = param_value;
                points.emplace_back(Point(lat_lon));
                boost::replace_all(param_name, " ", "");
                boost::replace_all(param_name, "loc[", "");
                boost::replace_all(param_name, "]", "");
                int loc_index = stoi(param_name);
                m_points.emplace(make_pair(loc_index, Point(lat_lon)));
              }
              else if (param_name == "loc")
              {
                lat_lon = param_value;
                points.emplace_back(Point(lat_lon));
              }
              else if (param_name == "type_query")
              {
                method_name = param_value;
              }
            }
            else param_name = x;
          }
        }
        s = m.suffix().str();
      }

      auto routing=[&](int point_id, vector<Point>& points, bool is_toll = false)->vector<ResponseOSRM>{
        vector<ResponseOSRM> result;
        try
        {
          RouteParameters params;
          json::Object osrm_result;
          params.annotations_type = engine::api::RouteParameters::AnnotationsType::All;
          for(Point& point : points)
            params.coordinates.push_back({util::FloatLongitude{point.longitude}, util::FloatLatitude{point.latitude}});
          params.alternatives = false;
          Point prev_point;
          int cnt = 0;
          int points_distance = 0;
          for (Point point : points)
          {
            if (cnt == 0) { prev_point = point; cnt++; continue; }
            points_distance += traffic.distance(prev_point, point);
            prev_point = point;
            cnt++;
          }
          if (points_distance < 250)
          {
            ResponseOSRM response_osrm;
            response_osrm.distance = points_distance;
            response_osrm.duration = ceil(float(points_distance)/3.6);
            response_osrm.loc_id = point_id;
            response_osrm.geometry = "";
            response_osrm.points.emplace_back(points.at(0));
            response_osrm.points.emplace_back(points.at(points.size() - 1));
            result.emplace_back(response_osrm);
            return result;
          }

          //const auto rstatus = OSRMS::Instance().get_osrm()->Route(params, osrm_result);
          Status rstatus;
          if (!is_toll)
          {
            //BOOST_LOG_SEV(lg, info) << init_request;
            std::shared_lock<std::shared_timed_mutex> lock{mutex_osrm};
            rstatus = OSRMS::Instance().get_osrm()->Route(params, osrm_result);
          }
          else
          {
            BOOST_LOG_SEV(lg, info) << init_request;
            std::shared_lock<std::shared_timed_mutex> lock{mutex_osrm_toll};
            rstatus = OSRMS::Instance().get_toll_osrm()->Route(params, osrm_result);
          }

          if (rstatus == Status::Ok)
          {
            json::Array& routes = osrm_result.values["routes"].get<json::Array>();
            if (routes.values.size() == 0)
            {
              using namespace Queue;
              RoutePoints route_points(points.at(0).latitude, points.at(0).longitude, points.at(points.size() - 1).latitude, points.at(points.size() - 1).longitude);
              unique_lock<mutex> lock{mutex_orm};
              queue_orm.push(Message(FAULT, route_points));
              lock.unlock();
              cond_orm.notify_one();
              ResponseOSRM response_osrm;
              response_osrm.loc_id = point_id;
              response_osrm.geometry = "";
              response_osrm.distance = -1;
              response_osrm.duration = -1;
              response_osrm.points.emplace_back(points.at(0));
              response_osrm.points.emplace_back(points.at(points.size() - 1));
              result.emplace_back(response_osrm);
              return result;
            }
            auto node = routes.values.at(0);
            json::Object route = node.get<json::Object>();
            ResponseOSRM response_osrm;
            response_osrm.loc_id = point_id;
            string geometry = route.values["geometry"].get<json::String>().value;
            int duration = route.values["duration"].get<json::Number>().value;
            float distance = route.values["distance"].get<json::Number>().value;

            vector<ULLINT> route_nodes;
            map<ULLINT, int> nodes_durations;
            deque<int> route_durations;
            for (auto t : route.values["legs"].get<json::Array>().values)
            {
              json::Array &nodes = t.get<json::Object>().values["annotation"].get<json::Object>().values["nodes"].get<json::Array>();
              for (auto rnode : nodes.values) route_nodes.emplace_back(rnode.get<json::Number>().value);
              json::Array &durations = t.get<json::Object>().values["annotation"].get<json::Object>().values["duration"].get<json::Array>();
              for (auto rduration : durations.values) route_durations.emplace_back(rduration.get<json::Number>().value);
            }
            if (route_nodes.size() > 0)
            {
              int total_time = 0;
              for (ULLINT node_id : route_nodes)
              {
                if (node_id == route_nodes.at(0)) { nodes_durations.emplace(make_pair(node_id, 0)); continue; }
                total_time += route_durations.front();
                route_durations.pop_front();
                nodes_durations.emplace(make_pair(node_id, total_time));
              }
            }
            if (traffic.get_access(nodes_durations))
            {
              response_osrm.geometry = geometry;
              response_osrm.distance = distance;
              response_osrm.duration = duration;
              response_osrm.points.emplace_back(points.at(0));
              response_osrm.points.emplace_back(points.at(points.size() - 1));
              result.emplace_back(response_osrm);
            }
          }
          else
          {
            ResponseOSRM response_osrm;
            if (points_distance < 250)
            {
              response_osrm.distance = points_distance;
              response_osrm.duration = ceil(float(points_distance)/3.6);;
            }
            else
            {
              response_osrm.distance = -1;
              response_osrm.duration = -1;
              using namespace Queue;
              RoutePoints route_points(points.at(0).latitude, points.at(0).longitude, points.at(points.size() - 1).latitude, points.at(points.size() - 1).longitude);
              unique_lock<mutex> lock{mutex_orm};
              queue_orm.push(Message(FAULT, route_points));
              lock.unlock();
              cond_orm.notify_one();
            }
            response_osrm.loc_id = point_id;
            response_osrm.geometry = "";
            response_osrm.points.emplace_back(points.at(0));
            response_osrm.points.emplace_back(points.at(points.size() - 1));
            result.emplace_back(response_osrm);
            return result;
          }
        }
        catch(std::exception& e)
        {
          cerr << currentDateTime() << " [error] route::GET::routing: " << e.what() << endl;
        }
        catch (...)
        {
          cerr << currentDateTime() << " [error] route::GET::routing: default exception" << endl;
        }
        return result;
      };

      if (!is_array && points.size() < 2)
      {
        cerr << currentDateTime() << " [error] route::get: " << s << endl;
        throw std::invalid_argument("The number of waypoints is less than 2");
      }

      vector<ResponseOSRM> responses;

      if (is_array)
      {
        auto it_zero = m_points.find(0);
        Point zero_point = it_zero->second;
        int cnt = 0;
        for (pair<int, Point> point : m_points)
        {
          cnt++;
          int point_id = point.first;
          double latitude = point.second.latitude;
          double longitude = point.second.longitude;

          if (latitude == zero_point.latitude && longitude == zero_point.longitude && cnt == 1) continue;

          if (latitude == zero_point.latitude && longitude == zero_point.longitude && cnt > 1)
          {
            ResponseOSRM response_osrm;
            response_osrm.loc_id = point_id;
            response_osrm.geometry = "";
            response_osrm.distance = 0;
            response_osrm.duration = 0;

            if (method_name == "2")
            {
              response_osrm.points.emplace_back(Point(latitude, longitude));
              response_osrm.points.emplace_back(Point(zero_point.latitude, zero_point.longitude));
            }
            else if (method_name == "10")
            {
              response_osrm.points.emplace_back(Point(zero_point.latitude, zero_point.longitude));
              response_osrm.points.emplace_back(Point(latitude, longitude));
            }
            responses.emplace_back(response_osrm);
            continue;
          }

          vector<Point> points;
          if (method_name == "2")
          {
            points.emplace_back(Point(latitude, longitude));
            points.emplace_back(Point(zero_point.latitude, zero_point.longitude));
          }
          else if (method_name == "10")
          {
            points.emplace_back(Point(zero_point.latitude, zero_point.longitude));
            points.emplace_back(Point(latitude, longitude));
          }
          vector<ResponseOSRM> result = routing(point_id, points);
          if (result.size() == 0)
          {
            map<double,Point> distances_to_bridges, distances_to_toll_roads;
            for(Bridge p : bridges)
            {
              Point p1(p.latitude, p.longitude);
              double dist_to_bridge = traffic.distance(points.at(points.size() - 1), p1);
              distances_to_bridges.emplace(make_pair(dist_to_bridge, p1));
            }
            for(Bridge p : toll_roads)
            {
              Point p1(p.latitude, p.longitude);
              double dist_to_road = traffic.distance(points.at(points.size() - 1), p1);
              distances_to_toll_roads.emplace(make_pair(dist_to_road, p1));
            }
            bool is_find = false;
            for (pair<double,Point> point : distances_to_bridges)
            {
              vector<Point> r_points;
              r_points.emplace_back(points.at(0));
              r_points.emplace_back(point.second);
              r_points.emplace_back(points.at(points.size() - 1));
              vector<ResponseOSRM> r_result = routing(point_id, r_points);
              if (r_result.size() > 0)
              {
                is_find = true;
                responses.emplace_back(r_result.at(0));
                break;
              }
            }
            if (!is_find)
            {
              for (pair<double,Point> point : distances_to_toll_roads)
              {
                vector<Point> r_points;
                r_points.emplace_back(points.at(0));
                r_points.emplace_back(point.second);
                r_points.emplace_back(points.at(points.size() - 1));
                // start routing
                vector<ResponseOSRM> r_result = routing(point_id, r_points, true);
                if (r_result.size() > 0)
                {
                  is_find = true;
                  responses.emplace_back(r_result.at(0));
                  break;
                }
              }
            }
            if (!is_find)
            { 
              using namespace Queue;
              RoutePoints route_points(points.at(0).latitude, points.at(0).longitude, points.at(points.size() - 1).latitude, points.at(points.size() - 1).longitude);
              unique_lock<mutex> lock{mutex_orm};
              queue_orm.push(Message(FAULT, route_points));
              lock.unlock();
              cond_orm.notify_one();
              ResponseOSRM response_osrm;
              response_osrm.loc_id = point_id;
              response_osrm.geometry = "";
              response_osrm.distance = -1;
              response_osrm.duration = -1;
              response_osrm.points.emplace_back(points.at(0));
              response_osrm.points.emplace_back(points.at(points.size() - 1));
              responses.emplace_back(response_osrm);
            }
          }
          else responses.emplace_back(result.at(0));
        }
      }
      else
      {
        vector<ResponseOSRM> result = routing(1, points);
        if (result.size() == 0)
        {
          map<double,Point> distances_to_bridges, distances_to_toll_roads;
          for(Bridge p : bridges)
          {
            Point p1(p.latitude, p.longitude);
            double dist_to_bridge = traffic.distance(points.at(points.size() - 1), p1);
            distances_to_bridges.emplace(make_pair(dist_to_bridge, p1));
          }
          for(Bridge p : toll_roads)
          {
            Point p1(p.latitude, p.longitude);
            double dist_to_road = traffic.distance(points.at(points.size() - 1), p1);
            distances_to_toll_roads.emplace(make_pair(dist_to_road, p1));
          }
          bool is_find = false;
          for (pair<double,Point> point : distances_to_bridges)
          {
            vector<Point> r_points;
            r_points.emplace_back(points.at(0));
            r_points.emplace_back(point.second);
            r_points.emplace_back(points.at(points.size() - 1));
            vector<ResponseOSRM> r_result = routing(1, r_points);
            if (r_result.size() > 0)
            {
              is_find = true;
              responses.emplace_back(r_result.at(0));
              break;
            }
          }
          if (!is_find)
          {
            for (pair<double,Point> point : distances_to_toll_roads)
            {
              vector<Point> r_points;
              r_points.emplace_back(points.at(0));
              r_points.emplace_back(point.second);
              r_points.emplace_back(points.at(points.size() - 1));
              // start routing
              vector<ResponseOSRM> r_result = routing(1, r_points, true);
              if (r_result.size() > 0)
              {
                is_find = true;
                responses.emplace_back(r_result.at(0));
                break;
              }
            }
          }
          if (!is_find)
          {
            using namespace Queue;
            RoutePoints route_points(points.at(0).latitude, points.at(0).longitude, points.at(points.size() - 1).latitude, points.at(points.size() - 1).longitude);
            unique_lock<mutex> lock{mutex_orm};
            queue_orm.push(Message(FAULT, route_points));
            lock.unlock();
            cond_orm.notify_one();
            ResponseOSRM response_osrm;
            response_osrm.loc_id = 1;
            response_osrm.geometry = "";
            response_osrm.distance = -1;
            response_osrm.duration = -1;
            response_osrm.points.emplace_back(points.at(0));
            response_osrm.points.emplace_back(points.at(points.size() - 1));
            responses.emplace_back(response_osrm);
          }
        }
        else responses.emplace_back(result.at(0));
      }

      int runtime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - t1).count();

      if (method_name == "1")
      {
        if (responses.size() > 0)
        {
          ResponseOSRM resp = responses.at(0);
          int hours = floor(resp.duration/3600);
          int minutes = floor(resp.duration/60) - hours * 60;
          int km = floor(resp.distance/1000);
          int meters = resp.distance - km * 1000;
          resp_json = "{\"gid_status\":\"" + to_string(1) + "\",\"h\":\"" + to_string(hours) + "\",\"km\":\"" + to_string(km) + "\",\"m\":\"" + to_string(meters) + "\",\"min\":\"" + to_string(minutes) + "\",\"status\":\"" + to_string(1) + "\",\"runtime\":\"" + to_string(runtime) + "\"}";
        }
        else resp_json = R"({"gid_status":"0","status":"0"})";
      }
      else if (method_name == "2")
      {
        if (responses.size() > 0)
        {
          resp_json = R"({"distances":[)";
          for (ResponseOSRM& resp : responses)
          {
            resp_json += R"({"distance":")" + to_string(int(resp.distance)) + R"(","lat":")" + to_string(resp.points.at(0).latitude) + R"(","lng":")" + to_string(resp.points.at(0).longitude) + R"(","loc_id":")" + to_string(resp.loc_id) + R"(","time":")" + to_string(int(resp.duration)) + R"("},)";
          }
          resp_json.pop_back();
          //resp_json += R"(],"status":"1"})";
          resp_json += R"(],"status":"1","runtime":")" + to_string(runtime) + R"("})";
        }
        else resp_json = R"({"status":"0"})";
      }
      else if (method_name == "10")
      {
        if (responses.size() > 0)
        {
          resp_json = R"({"distances":[)";
          for (ResponseOSRM& resp : responses)
          {
            resp_json += R"({"distance":")" + to_string(int(resp.distance)) + R"(","lat":")" + to_string(resp.points.at(1).latitude) + R"(","lng":")" + to_string(resp.points.at(1).longitude) + R"(","loc_id":")" + to_string(resp.loc_id) + R"(","time":")" + to_string(int(resp.duration)) + R"("},)";
          }
          resp_json.pop_back();
          //resp_json += R"(],"status":"1"})";
          resp_json += R"(],"status":"1","runtime":")" + to_string(runtime) + R"("})";
        }
        else resp_json = R"({"status":"0"})";
      }
      else if (method_name == "3")
      {
        if (responses.size() > 0)
        {
          ResponseOSRM resp = responses.at(0);
          resp_json = R"({"jam":")" + to_string(traffic.get_current_jam()) + R"(","route_summary":{"total_distance":)" + to_string(int(resp.distance)) + R"(,"total_time":)" + to_string(int(resp.duration)) + R"(},"status":"1","runtime":")" + to_string(runtime) + R"("})";
        }
        else resp_json = R"({"status":"0"})";
      }
      else if (method_name == "4")
      {
        if (responses.size() > 0)
        {
          ResponseOSRM resp = responses.at(0);
          resp_json = R"({"route_geometry":")" + url_encode(resp.geometry) + R"(","route_summary":{"total_distance":)" + to_string(int(resp.distance)) + R"(,"total_time":)" + to_string(int(resp.duration)) + R"(},"status":"1","runtime":")" + to_string(runtime) + R"("})";
        }
        else resp_json = R"({"status":"0"})";
      }

      *response << "HTTP/1.1 200 OK\r\n"
                << "Access-Control-Allow-Origin: *\r\n"
                << "Content-Type: application/json\r\n"
                << "Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers\r\n"
                << "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\r\n"
                << "Content-Length: " << resp_json.length() << "\r\n\r\n"
                << resp_json;
    }
    catch(std::exception& e) {
      string reason(e.what());
      if (reason != "points invalid") cerr << currentDateTime() << " [error] /route GET: " << e.what() << endl;
      *response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << reason.length() << "\r\n\r\n" << reason;
    }
    catch (...)
    {
      string reason = "default exception";
      cerr << currentDateTime() << " [error] route::GET::routing: default exception" << endl;
      *response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << reason.length() << "\r\n\r\n" << reason;
    }
  };

OSRMS class:

class OSRMS
{
private:
  EngineConfig      config;
  EngineConfig      second_config;
  EngineConfig      toll_config;
  EngineConfig      toll_second_config;
  OSRM*             first;
  OSRM*             second;
  OSRM*             toll;
  OSRM*             toll_second;
  bool              is_reload;
  bool              is_reload_toll;
public:
  static OSRMS& Instance()
  {
    static OSRMS myInstance;
    return myInstance;
  }
  const OSRM* get_osrm() const
  {
    if (is_reload) return this->second;
    else return this->first;
  }
  const OSRM* get_toll_osrm() const
  {
    if (is_reload_toll) return this->toll_second;
    else return this->toll;
  }
  void reload_config()
  {
    try
    {
      cout << currentDateTime() << " [info] Start reload OSRM First" << endl;
      is_reload = true;
      this_thread::sleep_for(chrono::seconds(5)); // wait for end first instance requests
      cout << currentDateTime() << " [info] Start reindex OSRM First" << endl;
      string command = "cd /osrm && osrm-contract northwestern-fed-district-latest.osrm --segment-speed-file /osrm/traffic.csv --level-cache true > /dev/null";
      system(command.c_str());
      cout << currentDateTime() << " [info] Finish reindex OSRM First" << endl;
      std::unique_lock<std::shared_timed_mutex> lock{mutex_osrm};
      delete first;
      first = new OSRM{config};
      lock.unlock();
      cout << currentDateTime() << " [info] Finish reload OSRM First instance" << endl;

      cout << currentDateTime() << " [info] Start reload OSRM Second instance" << endl;
      is_reload = false;
      this_thread::sleep_for(chrono::seconds(5)); // wait for end first instance requests
      cout << currentDateTime() << " [info] Start reindex OSRM Second" << endl;
      command = "cd /osrm/second && osrm-contract northwestern-fed-district-latest.osrm --segment-speed-file /osrm/traffic.csv --level-cache true > /dev/null";
      system(command.c_str());
      cout << currentDateTime() << " [info] Finish reindex OSRM Second" << endl;
      lock.lock();
      delete second;
      second = new OSRM{second_config};
      lock.unlock();

      cout << currentDateTime() << " [info] Start reload OSRM Toll First" << endl;
      is_reload_toll = true;
      this_thread::sleep_for(chrono::seconds(5)); // wait for end first toll instance requests
      cout << currentDateTime() << " [info] Start reindex OSRM Toll First" << endl;
      command = "cd /osrm/toll && osrm-contract northwestern-fed-district-latest.osrm --segment-speed-file /osrm/traffic.csv --level-cache true > /dev/null";
      system(command.c_str());
      cout << currentDateTime() << " [info] Finish reindex OSRM Toll First" << endl;
      std::unique_lock<std::shared_timed_mutex> lock_toll{mutex_osrm_toll};
      delete toll;
      toll = new OSRM{toll_config};
      lock_toll.unlock();
      cout << currentDateTime() << " [info] Finish reload OSRM Toll First instance" << endl;

      cout << currentDateTime() << " [info] Start reload OSRM Toll Second" << endl;
      is_reload_toll = false;
      this_thread::sleep_for(chrono::seconds(5)); // wait for end second toll instance requests
      cout << currentDateTime() << " [info] Start reindex OSRM Toll Second" << endl;
      command = "cd /osrm/toll_second && osrm-contract northwestern-fed-district-latest.osrm --segment-speed-file /osrm/traffic.csv --level-cache true > /dev/null";
      system(command.c_str());
      cout << currentDateTime() << " [info] Finish reindex OSRM Toll Second" << endl;
      lock_toll.lock();
      delete toll_second;
      toll_second = new OSRM{toll_second_config};
      lock_toll.unlock();
      cout << currentDateTime() << " [info] Finish reload OSRM Toll Second instance" << endl;
      cout << currentDateTime() << " [info] Finish reload config" << endl;
    }
    catch(const std::exception& e)
    {
      cerr << currentDateTime() << " [error] OSRMS::reload_config: " << e.what() << endl;
    }
  }
  OSRMS(OSRMS const&) = delete;             // Copy construct
  OSRMS(OSRMS&&) = delete;                  // Move construct
  OSRMS& operator=(OSRMS const&) = delete;  // Copy assign
  OSRMS& operator=(OSRMS &&) = delete;      // Move assign
protected:
  OSRMS()
  {
    is_reload = false;

    config.storage_config                 = {"/osrm/northwestern-fed-district-latest.osrm"};
    config.use_shared_memory              = false;
    first                                 = new OSRM{config};

    second_config.storage_config          = {"/osrm/second/northwestern-fed-district-latest.osrm"};
    second_config.use_shared_memory       = false;
    second                                = new OSRM{second_config};

    is_reload_toll = false;

    toll_config.storage_config            = {"/osrm/toll/northwestern-fed-district-latest.osrm"};
    toll_config.use_shared_memory         = false;
    toll                                  = new OSRM{toll_config};

    toll_second_config.storage_config     = {"/osrm/toll_second/northwestern-fed-district-latest.osrm"};
    toll_second_config.use_shared_memory  = false;
    toll_second                           = new OSRM{toll_second_config};
  }
  ~OSRMS()
  {
    delete first;
    delete toll;
    delete second;
    delete oll_second;
  }
};

@AlekseiSolonkov
Copy link
Author

AlekseiSolonkov commented Sep 18, 2017

When traffic is not used and car.lua default, the system works stably
traffic.csv.tar.gz

@danpat
Copy link
Member

danpat commented Sep 18, 2017

I strongly suspect a race condition in your locking logic, and you are delete-ing a valid OSRM object while a Route call is still running - are you sure that the mutexes are the same between the two objects?

I would also try with an empty traffic.csv file (no lines) - try to eliminate the possibility that it is a data bug.

If you find a particular traffic.csv file causes the crash, see if you can reproduce the crash in a single-threaded environment.

The OSRM object is thread-safe - many callers should work just fine.

@AlekseiSolonkov
Copy link
Author

AlekseiSolonkov commented Sep 18, 2017

Mutexes are the same. Is it necessary to re-create the object of the OSRM after complete osrm-contract? And is it possible to use an object created on a configuration that is currently running an osrm-contract?

@danpat
Copy link
Member

danpat commented Sep 18, 2017

Yes, it is necessary, the data needs to be re-loaded.

I have an idea what the problem might be - the .fileIndex file is accessed via mmap() - if you run osrm-contractwhile an OSRM() object is using it, you will corrupt the existing OSRM object.

You should run osrm-contract in a new temporary directory on a copy of the datafiles, then construct the new OSRM() object pointing at the fresh data - do not run osrm-contract on already loaded datafiles, some of them are mmap()-ed and if they change, you will break things.

@AlekseiSolonkov
Copy link
Author

Now I implement this idea in the code and check. Thank you!

@danpat
Copy link
Member

danpat commented Sep 18, 2017

Greato.

Closing this, as I don't think the problem is inside OSRM, rather it's how it was used in this case.

@danpat danpat closed this as completed Sep 18, 2017
@AlekseiSolonkov
Copy link
Author

(gdb) backtrace
#0 0x00007fb4deef6441 in QSqlDatabase::close() () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#1 0x00007fb4deef8ab9 in QSqlDatabase::~QSqlDatabase() () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#2 0x00007fb4deefb7ad in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#3 0x00007fb4dcc29019 in QHashData::free_helper(void ()(QHashData::Node)) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#4 0x00007fb4deef6197 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Sql.so.5
#5 0x00007fb4dbcc82e0 in __run_exit_handlers (status=11, listp=0x7fb4dc04f5d8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:83
#6 0x00007fb4dbcc833a in __GI_exit (status=) at exit.c:105
#7 0x000055a11c247413 in signalHandler(int) ()
#8
#9 0x00007fb4dd4900ba in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#10 0x00007fb4dd49018b in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#11 0x00007fb4dd491ce8 in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#12 0x00007fb4dd490692 in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#13 0x00007fb4dd48b0f4 in ?? () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#14 0x00007fb4dd48b1ac in tbb::task_scheduler_init::initialize(int, unsigned long) () from /usr/lib/x86_64-linux-gnu/libtbb.so.2
#15 0x000055a11c3092b5 in osrm::engine::Engineosrm::engine::routing_algorithms::corech::Algorithm::Engine(osrm::engine::EngineConfig const&) ()
#16 0x000055a11c30a528 in osrm::OSRM::OSRM(osrm::engine::EngineConfig&) ()
#17 0x000055a11c290dce in std::__shared_ptr<osrm::OSRM, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocatorosrm::OSRM, osrm::engine::EngineConfig&>(std::_Sp_make_shared_tag, std::allocatorosrm::OSRM const&, osrm::engine::EngineConfig&) ()
#18 0x000055a11c291832 in OSRMS::reload_config() ()
#19 0x000055a11c2cbc9a in Traffic::sync() ()
#20 0x000055a11c258efd in std::thread::_State_impl<std::_Bind_simple<main::{lambda()#11} ()> >::_M_run() ()
#21 0x00007fb4dc63050f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#22 0x00007fb4dc9046ca in start_thread (arg=0x7fb4a3330700) at pthread_create.c:333
#23 0x00007fb4dbd96caf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:105

@danpat
Copy link
Member

danpat commented Sep 18, 2017

In this case, I think an exception is being thrown that you're not properly catching.

Try adding catch (const osrm::exception &e) { std::cout << e; abort(); } to the try block in reload_config()

You can also try disabling the Qt default signal handler, but I don't know how to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants