Closed
Description
- I confirm that this is an issue rather than a question.
Bug report
Steps to reproduce
Send a lot of color
commands.
Here's my current code. It's using this visualizer as an external binary: https://github.com/karlstav/cava then modifying the data from that a little and turning it into commands for Hyperion.
Config for cava:
[general]
framerate = 40
autosens = 1
bars = 10
[input]
method = pulse
source = alsa_output.platform-soc_sound.stereo-fallback.monitor
[output]
method = raw
channels = stereo
raw_target = /dev/stdout
bit_format = 8bit
[smoothing]
integral = 5
gravity = 200
Node.js code (it's a work in progress):
import net from "net";
import { spawn } from "child_process";
import process from "process";
const PRIORITY = 5;
// Which bar should be displayed for each LED, in order of LEDs
const LED_MAP = [5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
// Hue of each LED
const HUE_MAP = [0, 0.2, 0.4, 0.6, 0.8, 0.8, 0.6, 0.4, 0.2, 0];
const hyperion = net.createConnection({ port: 19444 }, () => {
console.log("Connected to Hyperion");
});
hyperion.on("end", (data) => {
console.log("Disconnected from Hyperion");
});
process.on("SIGINT", () => {
hyperion.write(JSON.stringify({
command: "clear",
priority: PRIORITY,
}) + "\n");
hyperion.destroy();
process.exit();
});
const cava = spawn("/home/pi/src/cava/cava", ["-p", "/home/pi/visualizer.conf"], {
stdio: ["ignore", "pipe", "inherit"],
});
const pending = [];
let partial = null;
cava.stdout.on("data", (data) => {
let pointer = 0;
const totalLength = data.length;
while (pointer < totalLength) {
const missingBytes = partial == null ? 10 : 10 - partial.length;
const remaining = totalLength - pointer;
if (remaining >= missingBytes) {
pending.push(partial == null ? data.slice(pointer, missingBytes) : Buffer.concat([partial, data.slice(pointer, missingBytes)]));
pointer += missingBytes;
partial = null;
continue;
}
if (partial == null)
partial = data.slice(pointer);
else
partial = Buffer.concat([partial, data.slice(pointer)]);
pointer += remaining;
}
if (pending.length)
setImmediate(update);
});
function update() {
if (pending.length == 0) return;
// Average all pending entries
const averages = pending.reduce((acc, buffer) => {
const intensities = [];
const buflen = buffer.length;
for (let i = 0; i < buflen; i++)
intensities.push(buffer.readUInt8(i));
return acc.map((sum, i) => sum + intensities[i]);
}, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).map((sum) => sum / pending.length);
// Empty pending data
pending.length = 0;
const values = [];
for (const [ledIndex, sampleIndex] of LED_MAP.entries()) {
const color = hsltorgb(HUE_MAP[ledIndex], 1, (averages[sampleIndex] / 255) ** 2);
values.push(...color);
}
hyperion.write(JSON.stringify({
command: "color",
color: values,
priority: PRIORITY,
origin: "visualizer.mjs",
}) + "\n");
}
// h 0 through 1
// s 0 through 1
// l 0 through 1
function hsltorgb(h, s, l) {
const c = (1 - Math.abs(2 * l - 1)) * s;
const hh = h * 6;
const x = c * (1 - Math.abs(hh % 2 - 1));
const p = Math.floor(hh);
const m = Math.abs(l - c / 2);
const rgb = (
p === 0 ? [c, x, 0] :
p === 1 ? [x, c, 0] :
p === 2 ? [0, c, x] :
p === 3 ? [0, x, c] :
p === 4 ? [x, 0, c] :
p === 5 ? [c, 0, x] :
[0, 0, 0]
);
return [
Math.round(255 * (rgb[0] + m)),
Math.round(255 * (rgb[1] + m)),
Math.round(255 * (rgb[2] + m)),
];
}
What is expected?
No crash.
What is actually happening?
Within a couple of minutes, sometimes much faster, Hyperion crashes.
Samples from my syslog:
Mar 24 20:30:45 loungebox hyperiond[16843]: Hyperion caught signal :SIGSEGV
Mar 24 20:30:45 loungebox hyperiond[16843]: 2022-03-24T20:30:45.346 CORE : <ERROR> #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5461120]
Mar 24 20:30:45 loungebox [16843]: #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5461120]
Mar 24 20:30:45 loungebox systemd[1]: [email protected]: Main process exited, code=killed, status=11/SEGV
Mar 24 20:30:45 loungebox systemd[1]: [email protected]: Failed with result 'signal'.
Mar 24 20:57:43 loungebox hyperiond[4192]: Hyperion caught signal :SIGSEGV
Mar 24 20:57:43 loungebox hyperiond[4192]: 2022-03-24T20:57:43.921 CORE : <ERROR> #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5406120]
Mar 24 20:57:43 loungebox [4192]: #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5406120]
Mar 24 20:57:43 loungebox systemd[1]: [email protected]: Main process exited, code=killed, status=11/SEGV
Mar 24 20:57:43 loungebox systemd[1]: [email protected]: Failed with result 'signal'.
Mar 24 20:59:53 loungebox hyperiond[6938]: double free or corruption (!prev)
Mar 24 20:59:53 loungebox hyperiond[6938]: Hyperion caught signal :SIGABRT
Mar 24 20:59:53 loungebox hyperiond[6938]: 2022-03-24T20:59:53.210 CORE : <ERROR> #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5421120]
Mar 24 20:59:53 loungebox [6938]: #011/lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0) [0xb5421120]
Mar 24 20:59:53 loungebox systemd[1]: [email protected]: Main process exited, code=killed, status=6/ABRT
System
Hyperion Server:
- Build: (HEAD detached at 2.0.12) (GitHub-dc6aa4d/df14958-1637501177)
- Build time: Nov 21 2021 17:25:08
- Git Remote: https://github.com/hyperion-project/hyperion.ng
- Version: 2.0.12
- UI Lang: en (BrowserLang: en)
- UI Access: default
- Avail Capt: dispmanx,v4l2,framebuffer,qt
- Config path: /home/pi/.hyperion
- Database: read/write
Hyperion Server OS:
- Distribution: Raspbian GNU/Linux 10 (buster)
- Architecture: arm
- CPU Model: ARMv7 Processor rev 3 (v7l)
- CPU Type: Raspberry Pi 4 Model B Rev 1.4
- CPU Revision: b03114
- CPU Hardware: BCM2711
- Kernel: linux (5.10.103-v7l+ (WS: 32))
- Root/Admin: false
- Qt Version: 5.11.3
- Python Version: 3.7.3
- Browser: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0
- ```