Skip to content

Commit a80dea9

Browse files
julianoesmjbcopland
authored andcommitted
mavsdk_server: fix crash on stop/destruction (mavlink#2417)
This fixes a segfault which happens when the mavsdk_server is stopped and destroyed before every having discovered any autopilot. What happened is that: 1. ConnectionInitiator would be cancelled. 2. ConnectionInitiator would be destructed. 3. And only now the connect thread would wake up from sleeping and read the _should_exit flag which at this point has been destroyed. At this point the connect function would try to access Mavsdk::systems() which is also destructed by that point and cause a segfault. The fix is to wrap the ConnectionInitiator class in a shared ptr and keep that one alive in the connect function to avoid destruction until it has returned.
1 parent d7806a7 commit a80dea9

File tree

2 files changed

+12
-10
lines changed

2 files changed

+12
-10
lines changed

src/mavsdk_server/src/connection_initiator.h

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
#pragma once
22

3+
#include <atomic>
34
#include <chrono>
45
#include <future>
6+
#include <memory>
57
#include <mutex>
68
#include <thread>
79
#include <string>
810

911
#include "connection_result.h"
1012
#include "log.h"
13+
#include "mavsdk.h"
1114

1215
namespace mavsdk {
1316
namespace mavsdk_server {
1417

15-
template<typename Mavsdk> class ConnectionInitiator {
18+
class ConnectionInitiator : public std::enable_shared_from_this<ConnectionInitiator> {
1619
public:
17-
ConnectionInitiator() {}
18-
~ConnectionInitiator() {}
19-
20-
bool connect(Mavsdk& mavsdk, const std::string& connection_url)
20+
bool connect(mavsdk::Mavsdk& mavsdk, const std::string& connection_url)
2121
{
22-
LogInfo() << "Waiting to discover system on " << connection_url << "...";
22+
// Keep this class alive while this function is running.
23+
auto self = shared_from_this();
2324

2425
if (!add_any_connection(mavsdk, connection_url)) {
2526
return false;
@@ -49,7 +50,7 @@ template<typename Mavsdk> class ConnectionInitiator {
4950
void cancel() { _should_exit = true; }
5051

5152
private:
52-
bool add_any_connection(Mavsdk& mavsdk, const std::string& connection_url)
53+
bool add_any_connection(mavsdk::Mavsdk& mavsdk, const std::string& connection_url)
5354
{
5455
mavsdk::ConnectionResult connection_result = mavsdk.add_any_connection(connection_url);
5556

src/mavsdk_server/src/mavsdk_server.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class MavsdkServer::Impl {
1616

1717
bool connect(const std::string& connection_url)
1818
{
19-
return _connection_initiator.connect(_mavsdk, connection_url);
19+
_connection_initiator = std::make_shared<ConnectionInitiator>();
20+
return _connection_initiator->connect(_mavsdk, connection_url);
2021
}
2122

2223
int startGrpcServer(const int port)
@@ -31,7 +32,7 @@ class MavsdkServer::Impl {
3132

3233
void stop()
3334
{
34-
_connection_initiator.cancel();
35+
_connection_initiator->cancel();
3536

3637
if (_server != nullptr) {
3738
_server->stop();
@@ -47,7 +48,7 @@ class MavsdkServer::Impl {
4748

4849
private:
4950
mavsdk::Mavsdk _mavsdk;
50-
ConnectionInitiator<mavsdk::Mavsdk> _connection_initiator;
51+
std::shared_ptr<ConnectionInitiator> _connection_initiator;
5152
std::unique_ptr<GrpcServer> _server;
5253
int _grpc_port;
5354
};

0 commit comments

Comments
 (0)