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

Fix most of the crash causes on script engine reload/shutdown #574

Merged
merged 2 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading