Skip to content

Commit

Permalink
Fix most of the crash causes on script engine reload/shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
ksuprynowicz committed Aug 18, 2023
1 parent d62a40d commit 166f722
Show file tree
Hide file tree
Showing 25 changed files with 221 additions and 83 deletions.
5 changes: 3 additions & 2 deletions interface/src/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7556,8 +7556,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptManagerPoint
*connection = scriptManager->connect(scriptManager.get(), &ScriptManager::scriptEnding, [scriptManager, connection]() {
// Request removal of controller routes with callbacks to a given script engine
auto userInputMapper = DependencyManager::get<UserInputMapper>();
userInputMapper->scheduleScriptEndpointCleanup(scriptManager->engine().get());
// V8TODO: Maybe we should wait until endpoint cleanup is finished before deleting the script engine if there are still crashes
// scheduleScriptEndpointCleanup will have the last instance of shared pointer to script manager
// so script manager will get deleted as soon as cleanup is done
userInputMapper->scheduleScriptEndpointCleanup(scriptManager);
QObject::disconnect(*connection);
});
}
Expand Down
2 changes: 1 addition & 1 deletion libraries/controllers/src/controllers/Actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace controller {
}

EndpointPointer ActionsDevice::createEndpoint(const Input& input) const {
return std::make_shared<ActionEndpoint>(input);
return ActionEndpoint::newEndpoint(input);
}

/*@jsdoc
Expand Down
2 changes: 1 addition & 1 deletion libraries/controllers/src/controllers/InputDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ namespace controller {
}

EndpointPointer InputDevice::createEndpoint(const Input& input) const {
return std::make_shared<InputEndpoint>(input);
return InputEndpoint::newEndpoint(input);
}

}
2 changes: 1 addition & 1 deletion libraries/controllers/src/controllers/StateController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Input::NamedVector StateController::getAvailableInputs() const {
EndpointPointer StateController::createEndpoint(const Input& input) const {
auto name = stateVariables[input.getChannel()];
ReadLambda& readLambda = const_cast<QHash<QString, ReadLambda>&>(_namedReadLambdas)[name];
return std::make_shared<LambdaRefEndpoint>(readLambda);
return LambdaRefEndpoint::newEndpoint(readLambda);
}

}
31 changes: 16 additions & 15 deletions libraries/controllers/src/controllers/UserInputMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <ScriptEngine.h>
#include <ScriptEngineCast.h>
#include <ScriptValue.h>
#include <ScriptManager.h>

#include "impl/conditionals/AndConditional.h"
#include "impl/conditionals/NotConditional.h"
Expand Down Expand Up @@ -92,9 +93,9 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) {
if (input.device == STANDARD_DEVICE) {
endpoint = std::make_shared<StandardEndpoint>(input);
} else if (input.device == ACTIONS_DEVICE) {
endpoint = std::make_shared<ActionEndpoint>(input);
endpoint = ActionEndpoint::newEndpoint(input);
} else {
endpoint = std::make_shared<InputEndpoint>(input);
endpoint = InputEndpoint::newEndpoint(input);
}
}
_inputsByEndpoint[endpoint] = input;
Expand Down Expand Up @@ -663,7 +664,7 @@ Endpoint::Pointer UserInputMapper::endpointFor(const QJSValue& endpoint) {
}

if (endpoint.isCallable()) {
auto result = std::make_shared<JSEndpoint>(endpoint);
auto result = JSEndpoint::newEndpoint(endpoint);
return result;
}

Expand All @@ -677,7 +678,7 @@ Endpoint::Pointer UserInputMapper::endpointFor(const ScriptValue& endpoint) {
}

if (endpoint.isFunction()) {
auto result = std::make_shared<ScriptEndpoint>(endpoint);
auto result = ScriptEndpoint::newEndpoint(endpoint);
return result;
}

Expand All @@ -692,7 +693,7 @@ Endpoint::Pointer UserInputMapper::endpointFor(const ScriptValue& endpoint) {
}
children.push_back(destination);
}
return std::make_shared<AnyEndpoint>(children);
return AnyEndpoint::newEndpoint(children);
}


Expand All @@ -715,7 +716,7 @@ Endpoint::Pointer UserInputMapper::compositeEndpointFor(Endpoint::Pointer first,
Endpoint::Pointer result;
auto iterator = _compositeEndpoints.find(pair);
if (_compositeEndpoints.end() == iterator) {
result = std::make_shared<CompositeEndpoint>(first, second);
result = CompositeEndpoint::newEndpoint(first, second);
_compositeEndpoints[pair] = result;
} else {
result = iterator->second;
Expand Down Expand Up @@ -858,9 +859,9 @@ void UserInputMapper::unloadMapping(const QString& jsonFile) {
}
}

void UserInputMapper::scheduleScriptEndpointCleanup(ScriptEngine* engine) {
void UserInputMapper::scheduleScriptEndpointCleanup(std::shared_ptr<ScriptManager> manager) {
_lock.lock();
scriptEnginesRequestingCleanup.enqueue(engine);
scriptManagersRequestingCleanup.enqueue(manager);
_lock.unlock();
}

Expand Down Expand Up @@ -1025,7 +1026,7 @@ Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {

Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) {
if (value.isArray()) {
ArrayEndpoint::Pointer result = std::make_shared<ArrayEndpoint>();
ArrayEndpoint::Pointer result = std::dynamic_pointer_cast<ArrayEndpoint>(ArrayEndpoint::newEndpoint());
auto array = value.toArray();
for (const auto& arrayItem : array) {
Endpoint::Pointer destination = parseEndpoint(arrayItem);
Expand All @@ -1052,7 +1053,7 @@ Endpoint::Pointer UserInputMapper::parseAxis(const QJsonValue& value) {
Endpoint::Pointer first = parseEndpoint(axisArray.first());
Endpoint::Pointer second = parseEndpoint(axisArray.last());
if (first && second) {
return std::make_shared<CompositeEndpoint>(first, second);
return CompositeEndpoint::newEndpoint(first, second);
}
}
}
Expand All @@ -1072,7 +1073,7 @@ Endpoint::Pointer UserInputMapper::parseAny(const QJsonValue& value) {
}
children.push_back(destination);
}
return std::make_shared<AnyEndpoint>(children);
return AnyEndpoint::newEndpoint(children);
}
return Endpoint::Pointer();
}
Expand Down Expand Up @@ -1261,8 +1262,8 @@ void UserInputMapper::disableMapping(const Mapping::Pointer& mapping) {
void UserInputMapper::runScriptEndpointCleanup() {
_lock.lock();
QList<RoutePointer> routesToRemove;
while (!scriptEnginesRequestingCleanup.empty()){
auto engine = scriptEnginesRequestingCleanup.dequeue();
while (!scriptManagersRequestingCleanup.empty()){
auto manager = scriptManagersRequestingCleanup.dequeue();
QList<RouteList*> routeLists = {&_deviceRoutes, &_standardRoutes};
auto iterator = _mappingsByName.begin();
while (iterator != _mappingsByName.end()) {
Expand All @@ -1274,12 +1275,12 @@ void UserInputMapper::runScriptEndpointCleanup() {
for (auto routeList: routeLists) {
for (auto route: *routeList) {
auto source = std::dynamic_pointer_cast<ScriptEndpoint>(route->source);
if (source && source->getEngine() == engine) {
if (source && source->getEngine() == manager->engine().get()) {
qDebug() << "UserInputMapper::runScriptEndpointCleanup source";
routesToRemove.append(route);
}
auto destination = std::dynamic_pointer_cast<ScriptEndpoint>(route->destination);
if (destination && destination->getEngine() == engine) {
if (destination && destination->getEngine() == manager->engine().get()) {
qDebug() << "UserInputMapper::runScriptEndpointCleanup destination";
routesToRemove.append(route);
}
Expand Down
5 changes: 3 additions & 2 deletions libraries/controllers/src/controllers/UserInputMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "StateController.h"

class ScriptEngine;
class ScriptManager;
class ScriptValue;

namespace controller {
Expand Down Expand Up @@ -136,7 +137,7 @@ namespace controller {
*
* @param engine Pointer to the script engine that will be shut down
*/
void scheduleScriptEndpointCleanup(ScriptEngine* engine);
void scheduleScriptEndpointCleanup(std::shared_ptr<ScriptManager> manager);

AxisValue getValue(const Input& input) const;
Pose getPose(const Input& input) const;
Expand Down Expand Up @@ -223,7 +224,7 @@ namespace controller {
InputCalibrationData inputCalibrationData;

// Contains pointers to script engines that are requesting callback cleanup during their shutdown process
QQueue<ScriptEngine*> scriptEnginesRequestingCleanup;
QQueue<std::shared_ptr<ScriptManager>> scriptManagersRequestingCleanup;

mutable std::recursive_mutex _lock;
};
Expand Down
30 changes: 19 additions & 11 deletions libraries/controllers/src/controllers/impl/Endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ namespace controller {
* Encapsulates a particular input / output,
* i.e. Hydra.Button0, Standard.X, Action.Yaw
*/
class Endpoint : public QObject {

// All the derived classes need to have private constructors
class Endpoint : public QObject, public std::enable_shared_from_this<Endpoint> {
Q_OBJECT;
public:
using Pointer = std::shared_ptr<Endpoint>;
Expand All @@ -36,7 +38,6 @@ namespace controller {
using ReadLambda = std::function<float()>;
using WriteLambda = std::function<void(float)>;

Endpoint(const Input& input) : _input(input) {}
virtual AxisValue value() { return peek(); }
virtual AxisValue peek() const = 0;
virtual void apply(AxisValue value, const Pointer& source) = 0;
Expand All @@ -51,19 +52,21 @@ namespace controller {
const Input& getInput() { return _input; }

protected:
Endpoint(const Input& input) : _input(input) {}
Input _input;
};

class LambdaEndpoint : public Endpoint {
public:
using Endpoint::apply;
LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {})
: Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { }

virtual AxisValue peek() const override { return AxisValue(_readLambda(), 0); }
virtual void apply(AxisValue value, const Pointer& source) override { _writeLambda(value.value); }

private:
LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {})
: Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { }

ReadLambda _readLambda;
WriteLambda _writeLambda;
};
Expand All @@ -72,26 +75,27 @@ namespace controller {

class LambdaRefEndpoint : public Endpoint {
public:
static std::shared_ptr<Endpoint> newEndpoint(const ReadLambda& readLambda, const WriteLambda& writeLambda = DEFAULT_WRITE_LAMBDA) {
return std::shared_ptr<Endpoint>(new LambdaRefEndpoint(readLambda, writeLambda));
};

using Endpoint::apply;
LambdaRefEndpoint(const ReadLambda& readLambda, const WriteLambda& writeLambda = DEFAULT_WRITE_LAMBDA)
: Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) {
}

virtual AxisValue peek() const override { return AxisValue(_readLambda(), 0); }
virtual void apply(AxisValue value, const Pointer& source) override { _writeLambda(value.value); }

private:
LambdaRefEndpoint(const ReadLambda& readLambda, const WriteLambda& writeLambda = DEFAULT_WRITE_LAMBDA)
: Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) {
}

const ReadLambda& _readLambda;
const WriteLambda& _writeLambda;
};


class VirtualEndpoint : public Endpoint {
public:
VirtualEndpoint(const Input& id = Input::INVALID_INPUT)
: Endpoint(id) {
}

virtual AxisValue peek() const override { return _currentValue; }
virtual void apply(AxisValue value, const Pointer& source) override { _currentValue = value; }

Expand All @@ -100,6 +104,10 @@ namespace controller {
_currentPose = value;
}
protected:
VirtualEndpoint(const Input& id = Input::INVALID_INPUT)
: Endpoint(id) {
}

AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose {};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ namespace controller {

class ActionEndpoint : public Endpoint {
public:
ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { }
static std::shared_ptr<Endpoint> newEndpoint(const Input& id = Input::INVALID_INPUT) {
return std::shared_ptr<Endpoint>(new ActionEndpoint(id));
};

virtual AxisValue peek() const override { return _currentValue; }
virtual void apply(AxisValue newValue, const Pointer& source) override;
Expand All @@ -32,6 +34,8 @@ class ActionEndpoint : public Endpoint {
virtual void reset() override;

private:
ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { }

AxisValue _currentValue { 0.0f, 0, false };
Pose _currentPose{};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ namespace controller {
class AnyEndpoint : public Endpoint {
friend class UserInputMapper;
public:
static std::shared_ptr<Endpoint> newEndpoint(Endpoint::List children) {
return std::shared_ptr<Endpoint>(new AnyEndpoint(children));
};

using Endpoint::apply;
AnyEndpoint(Endpoint::List children);
virtual AxisValue peek() const override;
virtual AxisValue value() override;
virtual void apply(AxisValue newValue, const Endpoint::Pointer& source) override;
virtual bool writeable() const override;
virtual bool readable() const override;

private:
AnyEndpoint(Endpoint::List children);

Endpoint::List _children;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ namespace controller {
class ArrayEndpoint : public Endpoint {
friend class UserInputMapper;
public:
static std::shared_ptr<Endpoint> newEndpoint() {
return std::shared_ptr<Endpoint>(new ArrayEndpoint());
};

using Endpoint::apply;
using Pointer = std::shared_ptr<ArrayEndpoint>;
ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { }

virtual AxisValue peek() const override { return AxisValue(); }

Expand All @@ -34,6 +37,7 @@ class ArrayEndpoint : public Endpoint {
virtual bool readable() const override { return false; }

private:
ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { }
Endpoint::List _children;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@
namespace controller {
class CompositeEndpoint : public Endpoint, Endpoint::Pair {
public:
static std::shared_ptr<Endpoint> newEndpoint(Endpoint::Pointer first, Endpoint::Pointer second) {
return std::shared_ptr<Endpoint>(new CompositeEndpoint(first, second));
};

using Endpoint::apply;
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second);

virtual AxisValue peek() const override;
virtual AxisValue value() override;
virtual void apply(AxisValue newValue, const Pointer& source) override;
virtual bool readable() const override;

private:
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second);
};

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ namespace controller {

class InputEndpoint : public Endpoint {
public:
InputEndpoint(const Input& id = Input::INVALID_INPUT)
: Endpoint(id) {
}
static std::shared_ptr<Endpoint> newEndpoint(const Input& id = Input::INVALID_INPUT) {
return std::shared_ptr<Endpoint>(new InputEndpoint(id));
};

virtual AxisValue peek() const override;
virtual AxisValue value() override;
Expand All @@ -34,6 +34,10 @@ class InputEndpoint : public Endpoint {
virtual void reset() override { _read = false; }

private:
InputEndpoint(const Input& id = Input::INVALID_INPUT)
: Endpoint(id) {
}

bool _read { false };
};

Expand Down
Loading

0 comments on commit 166f722

Please sign in to comment.