Browse Source

Fix crash due to non-aligned Port allocation

Signed-off-by: falkTX <falktx@falktx.com>
tags/22.02
falkTX 3 years ago
parent
commit
fdc18bc10f
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 27 additions and 20 deletions
  1. +9
    -6
      include/engine/Port.hpp
  2. +18
    -14
      src/override/Engine.cpp

+ 9
- 6
include/engine/Port.hpp View File

@@ -38,7 +38,7 @@ namespace engine {


/** This is inspired by the number of MIDI channels. */
static const int PORT_MAX_CHANNELS = 16;
static constexpr const int PORT_MAX_CHANNELS = 16;


struct Cable;
@@ -46,7 +46,9 @@ struct Cable;

struct Port {
/** Voltage of the port. */
union {
/** NOTE alignas is required in order to allow SSE usage.
Consecutive data (like in a vector) would otherwise pack Ports in a way that breaks SSE. */
union alignas(PORT_MAX_CHANNELS) {
/** Unstable API. Use getVoltage() and setVoltage() instead. */
float voltages[PORT_MAX_CHANNELS] = {};
/** DEPRECATED. Unstable API. Use getVoltage() and setVoltage() instead. */
@@ -72,9 +74,6 @@ struct Port {
OUTPUT,
};

/** List of cables connected to this port (if output type). */
std::list<Cable*> cables;

/** Sets the voltage of the given channel. */
void setVoltage(float voltage, int channel = 0) {
voltages[channel] = voltage;
@@ -236,7 +235,11 @@ struct Port {
};


struct Output : Port {};
struct Output : Port {
/** List of cables connected to this port. */
std::list<Cable*> cables;
};


struct Input : Port {};



+ 18
- 14
src/override/Engine.cpp View File

@@ -279,41 +279,45 @@ static void Port_setConnected(Port* that) {

static void Engine_updateConnected(Engine* that) {
// Find disconnected ports
std::set<Port*> disconnectedPorts;
std::set<Input*> disconnectedInputs;
std::set<Output*> disconnectedOutputs;
for (Module* module : that->internal->modules) {
for (Input& input : module->inputs) {
disconnectedPorts.insert(&input);
disconnectedInputs.insert(&input);
}
for (Output& output : module->outputs) {
disconnectedPorts.insert(&output);
disconnectedOutputs.insert(&output);
}
}
for (TerminalModule* terminalModule : that->internal->terminalModules) {
for (Input& input : terminalModule->inputs) {
disconnectedPorts.insert(&input);
disconnectedInputs.insert(&input);
}
for (Output& output : terminalModule->outputs) {
disconnectedPorts.insert(&output);
disconnectedOutputs.insert(&output);
}
}
for (Cable* cable : that->internal->cables) {
// Connect input
Input& input = cable->inputModule->inputs[cable->inputId];
auto inputIt = disconnectedPorts.find(&input);
if (inputIt != disconnectedPorts.end())
disconnectedPorts.erase(inputIt);
auto inputIt = disconnectedInputs.find(&input);
if (inputIt != disconnectedInputs.end())
disconnectedInputs.erase(inputIt);
Port_setConnected(&input);
// Connect output
Output& output = cable->outputModule->outputs[cable->outputId];
auto outputIt = disconnectedPorts.find(&output);
if (outputIt != disconnectedPorts.end())
disconnectedPorts.erase(outputIt);
auto outputIt = disconnectedOutputs.find(&output);
if (outputIt != disconnectedOutputs.end())
disconnectedOutputs.erase(outputIt);
Port_setConnected(&output);
}
// Disconnect ports that have no cable
for (Port* port : disconnectedPorts) {
Port_setDisconnected(port);
DISTRHO_SAFE_ASSERT(port->cables.empty());
for (Input* input : disconnectedInputs) {
Port_setDisconnected(input);
}
for (Output* output : disconnectedOutputs) {
Port_setDisconnected(output);
DISTRHO_SAFE_ASSERT(output->cables.empty());
}
}



Loading…
Cancel
Save