From 87870733382f768393e25cdb36360b0397a3eacd Mon Sep 17 00:00:00 2001 From: "Robin E. R. Davies" Date: Sun, 24 Nov 2024 12:41:30 -0500 Subject: [PATCH] Auto-select web server port (for Ubuntu); --port option for PiPedalConfig --- .vscode/c_cpp_properties.json | 2 +- .vscode/launch.json | 82 +++++---- .vscode/settings.json | 3 +- CMakeLists.txt | 2 +- LICENSE.txt | 2 +- NetworkManagerP2P/src/main.cpp | 2 +- NetworkManagerP2P/src/ss.hpp | 2 +- PiPedalCommon/src/HtmlHelper.cpp | 2 +- PiPedalCommon/src/Lv2Log.cpp | 2 +- PiPedalCommon/src/NetLinkChannelInfo.cpp | 2 +- PiPedalCommon/src/NetLinkChannelInfo.cpp.bak | 2 +- PiPedalCommon/src/json.cpp | 2 +- debian/copyright | 10 +- debian/fill.copyright.blanks.yml | 4 +- docs/LicensePiPedal.md | 2 +- docs/LicenseToobAmp.md | 2 +- react/src/PiPedalModel.tsx | 2 +- react/src/PiPedalSocket.tsx | 4 +- src/AvahiService.cpp | 1 + src/ConfigMain.cpp | 183 ++++++++++++++++--- src/Lv2PluginChangeMonitor.cpp | 2 +- src/SchedulerPriority.cpp | 56 +++--- src/Worker.cpp | 1 - 23 files changed, 261 insertions(+), 111 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d7afa68..db8fe47 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,7 +11,7 @@ "/usr/lib", "~/src/vst3sdk" ], - "compilerPath": "/usr/bin/gcc", + "compilerPath": "/usr/bin/gcc-12", "cStandard": "c17", "cppStandard": "c++20", "intelliSenseMode": "linux-gcc-arm64", diff --git a/.vscode/launch.json b/.vscode/launch.json index 6e6cf77..53bc7b3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -266,6 +266,48 @@ } ] }, + { + "name": "(gdb) pipedalconfigX", + "type": "cppdbg", + "request": "launch", + // Resolved by CMake Tools: + "program": "/home/robin/src/pipedal/build/src/pipedalconfig", + "args": [ + "--nosudo", // run without sudo (which will fail because of perms, but allow us to debug deeper into install code.) + //"--get-current-port" + // "--uninstall" + //"--enable-p2p" , "CA", "PiPedalTest","12345678","14" + // "--alsa-devices" + "--prefix", "/usr", + "--install", "--port", "0" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + { + "name": "PATH", + "value": "$PATH:${command:cmake.launchTargetDirectory}" + }, + { + "name": "ASAN_OPTIONS", + "value": "detect_leaks=0" + + }, + { + "name": "OTHER_VALUE", + "value": "Something something" + } + ], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, { @@ -312,46 +354,6 @@ } ] }, - { - "name": "(gdb) pipedalconfig", - "type": "cppdbg", - "request": "launch", - // Resolved by CMake Tools: - "program": "${command:cmake.launchTargetPath}", - "args": [ - "--nosudo", // run without sudo (which will fail because of perms, but allow us to debug deeper into install code.) - //"--get-current-port" - // "--uninstall" - //"--enable-p2p" , "CA", "PiPedalTest","12345678","14" - "--alsa-devices" - ], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [ - { - "name": "PATH", - "value": "$PATH:${command:cmake.launchTargetDirectory}" - }, - { - "name": "ASAN_OPTIONS", - "value": "detect_leaks=0" - - }, - { - "name": "OTHER_VALUE", - "value": "Something something" - } - ], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - }, { "name": "(gdb) pipedal_alsa_check", "type": "cppdbg", diff --git a/.vscode/settings.json b/.vscode/settings.json index b305b9b..029cef1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -110,5 +110,6 @@ "pipedalshutdownd", "pipedaltest", "ToobAmp" - ] + ], + "C_Cpp.default.compilerPath": "/usr/bin/g++-13" } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index e493246..21cf7aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ endif() set(CPACK_GENERATOR "DEB") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Robin E. R. Davies") # required -set(CPACK_PACKAGE_VENDOR "Robin Davies") +set(CPACK_PACKAGE_VENDOR "Robin E. R. Davies") set(CPACK_PACKAGE_DESCRIPTION "IoT guitar effect pedal for Raspberry Pi, with phone-friendly web interface.") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IoT guitar effect pedal for Raspberry Pi") set(CPACK_DEBIAN_PACKAGE_SECTION sound) diff --git a/LICENSE.txt b/LICENSE.txt index 1125614..a0619cb 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright 2021-2024 Robin Davies +Copyright 2021-2024 Robin E. R. Davies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/NetworkManagerP2P/src/main.cpp b/NetworkManagerP2P/src/main.cpp index c03d137..5ac848c 100644 --- a/NetworkManagerP2P/src/main.cpp +++ b/NetworkManagerP2P/src/main.cpp @@ -17,7 +17,7 @@ using namespace std; static void PrintHelp() { cout << "nm-pipedal-p2p - P2P Manager for NetworkManager network stack." << endl - << "Copyright (c) 2024 Robin Davies." << endl + << "Copyright (c) 2024 Robin E. R. Davies." << endl << endl << "Provides P2P connections on LINUX distributions that use NetworkManager." << endl << endl diff --git a/NetworkManagerP2P/src/ss.hpp b/NetworkManagerP2P/src/ss.hpp index 6b34c10..af6ce2e 100644 --- a/NetworkManagerP2P/src/ss.hpp +++ b/NetworkManagerP2P/src/ss.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Robin Davies +// Copyright (c) 2022 Robin E. R. Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in diff --git a/PiPedalCommon/src/HtmlHelper.cpp b/PiPedalCommon/src/HtmlHelper.cpp index ac7c218..9944bd5 100644 --- a/PiPedalCommon/src/HtmlHelper.cpp +++ b/PiPedalCommon/src/HtmlHelper.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Robin Davies +// Copyright (c) 2022 Robin E. R. Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in diff --git a/PiPedalCommon/src/Lv2Log.cpp b/PiPedalCommon/src/Lv2Log.cpp index 7b43bec..686f1c4 100644 --- a/PiPedalCommon/src/Lv2Log.cpp +++ b/PiPedalCommon/src/Lv2Log.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Robin Davies +// Copyright (c) 2022 Robin E. R. Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in diff --git a/PiPedalCommon/src/NetLinkChannelInfo.cpp b/PiPedalCommon/src/NetLinkChannelInfo.cpp index 7d24513..a88d343 100644 --- a/PiPedalCommon/src/NetLinkChannelInfo.cpp +++ b/PiPedalCommon/src/NetLinkChannelInfo.cpp @@ -3,7 +3,7 @@ Copyright (c) 2007, 2008 Johannes Berg Copyright (c) 2007 Andy Lutomirski Copyright (c) 2007 Mike Kershaw Copyright (c) 2008 Luis R. Rodriguez -Copyright (c) 2024 Robin Davies +Copyright (c) 2024 Robin E. R. Davies All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/PiPedalCommon/src/NetLinkChannelInfo.cpp.bak b/PiPedalCommon/src/NetLinkChannelInfo.cpp.bak index 0012cd6..8d0a8af 100644 --- a/PiPedalCommon/src/NetLinkChannelInfo.cpp.bak +++ b/PiPedalCommon/src/NetLinkChannelInfo.cpp.bak @@ -3,7 +3,7 @@ Copyright (c) 2007, 2008 Johannes Berg Copyright (c) 2007 Andy Lutomirski Copyright (c) 2007 Mike Kershaw Copyright (c) 2008 Luis R. Rodriguez -Copyright (c) 2024 Robin Davies +Copyright (c) 2024 Robin E. R. Davies All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/PiPedalCommon/src/json.cpp b/PiPedalCommon/src/json.cpp index 5b55fc6..c25f5ae 100644 --- a/PiPedalCommon/src/json.cpp +++ b/PiPedalCommon/src/json.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Robin Davies +// Copyright (c) 2022 Robin E. R. Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in diff --git a/debian/copyright b/debian/copyright index 6efca97..45dd967 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,24 +1,24 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: pipedal -Upstream-Contact: Robin Davies +Upstream-Contact: Robin E. R. Davies Source: https://www.example.com/software/project Files: * -Copyright: 2021, Robin Davies +Copyright: 2021, Robin E. R. Davies License: Expat Files: src/* -Copyright: 2021, Robin Davies +Copyright: 2021, Robin E. R. Davies License: Expat Files: react/src -Copyright: 2020, Robin Davies. +Copyright: 2020, Robin E. R. Davies. License: Expat Files: src/Lv2EventBufferWriter.hpp Copyright: 2008-2014, David Robillard - 2021, Robin Davies + 2021, Robin E. R. Davies License: ISC and Expat Files: react/node_modules/@babel/* diff --git a/debian/fill.copyright.blanks.yml b/debian/fill.copyright.blanks.yml index 1760ec1..15f83f9 100644 --- a/debian/fill.copyright.blanks.yml +++ b/debian/fill.copyright.blanks.yml @@ -1,11 +1,11 @@ --- /: license: Expat - copyright: 2021, Robin Davies. + copyright: 2021, Robin E. R. Davies. src/react/: license: Expat - copyright: 2021, Robin Davies. + copyright: 2021, Robin E. R. Davies. react/node_modules/webpack/: license: Expat diff --git a/docs/LicensePiPedal.md b/docs/LicensePiPedal.md index 516449c..8911e36 100644 --- a/docs/LicensePiPedal.md +++ b/docs/LicensePiPedal.md @@ -1,4 +1,4 @@ -Copyright 2021-2024 Robin Davies +Copyright 2021-2024 Robin E. R. Davies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/docs/LicenseToobAmp.md b/docs/LicenseToobAmp.md index 279f498..f55edb4 100644 --- a/docs/LicenseToobAmp.md +++ b/docs/LicenseToobAmp.md @@ -1,4 +1,4 @@ -Copyright 2021-2023 Robin Davies +Copyright 2021-2023 Robin E. R. Davies Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/react/src/PiPedalModel.tsx b/react/src/PiPedalModel.tsx index e001630..286869b 100644 --- a/react/src/PiPedalModel.tsx +++ b/react/src/PiPedalModel.tsx @@ -1014,7 +1014,7 @@ export class PiPedalModel //implements PiPedalModel try { await this.webSocket.connect(); } catch (error) { - this.setError("Failed to connect to server. (" + getErrorMessage(error)); + this.setError("Failed to connect to server. " + getErrorMessage(error) ); return false; } diff --git a/react/src/PiPedalSocket.tsx b/react/src/PiPedalSocket.tsx index 49315d7..d2257a8 100644 --- a/react/src/PiPedalSocket.tsx +++ b/react/src/PiPedalSocket.tsx @@ -281,7 +281,7 @@ class PiPedalSocket { ws.onerror = (evt: Event) => { ws.onclose = null; ws.onerror = null; - reject("Failed to connect."); + reject("Connection not accepted."); }; ws.onopen = (event: Event) => { ws.onerror = self.handleError.bind(self); @@ -290,7 +290,7 @@ class PiPedalSocket { resolve(ws); }; } catch (e: any){ - reject("Failed to connect. " + e.toString()); + reject("Failed to connect: " + e.toString()); }; }); } diff --git a/src/AvahiService.cpp b/src/AvahiService.cpp index f4f61f7..a3feb36 100644 --- a/src/AvahiService.cpp +++ b/src/AvahiService.cpp @@ -181,6 +181,7 @@ void AvahiService::EntryGroupCallback(AvahiEntryGroup *g, AvahiEntryGroupState s char *n = avahi_alternative_service_name(avahiNameString); avahi_free(avahiNameString); avahiNameString = n; + this->serviceName = n; Lv2Log::warning(SS("Service name collision, renaming service to '" << avahiNameString << "'\n")); /* And recreate the services */ create_group(avahi_entry_group_get_client(g)); diff --git a/src/ConfigMain.cpp b/src/ConfigMain.cpp index de5b78a..0e3d13e 100644 --- a/src/ConfigMain.cpp +++ b/src/ConfigMain.cpp @@ -27,6 +27,7 @@ #include "alsaCheck.hpp" #include "RegDb.hpp" #include "Locale.hpp" +#include "Finally.hpp" #include #include @@ -953,6 +954,110 @@ void InstallPgpKey() sysExec(cmd.c_str()); } } + + +static uint32_t autoSelectPorts[] = { + 80, + 81, // unofficial alternate + 8080, // unofficial alternate + 8081, // unofficial alternate + 8008, // unofficial alternate + 83 // Not official at all. + }; + + + +static bool isPortInUse(int port) { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + throw std::runtime_error(SS("Socket creation failed: " << strerror(errno))); + } + Finally ff{[sockfd]() { + close(sockfd); + }}; + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + // Try to bind to the port + int result = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)); + + if (result < 0) { + if (errno == EADDRINUSE) { + return true; // Port is in use + } else { + cout << "Warning: Unexpected error binding socket to port " << port << ": " << strerror(errno) << endl; + return true; + } + } + + return false; // Port is free +} + + +static std::string AutoSelectPort() { + constexpr size_t MAX_PORT = sizeof(autoSelectPorts)/sizeof(autoSelectPorts[0]); + + int32_t port = -1; + for (size_t i = 0; i < MAX_PORT; ++i) + { + if (!isPortInUse(autoSelectPorts[i])) + { + port = autoSelectPorts[i]; + break; + } + } + if (port == -1) { + cout << "Warning: Can't find an available HTTP port. Setting to port 80 anyway." << endl; + port = 80; + } else if (port != 80) + { + cout << "Warning: Port 80 is already in use. Using port " << port << " instead." << endl; + } + + return SS(port); + +} + + +bool SetWebServerPort(std::string portOption) +{ + + try { + auto nPos = portOption.find_last_of(':'); + std::string strPort; + if (nPos != std::string::npos) + { + strPort = portOption.substr(nPos+1); + } else { + strPort = portOption; + } + std::istringstream ss(strPort); + + uint16_t iPort = 0; + ss >> iPort; + if (!ss) + { + throw std::runtime_error(SS("Invalid port number: " << strPort)); + } + + StopService(false); + + PrepareServiceConfigurationFile(iPort); + + StartService(true); + + cout << "PiPedal web server is listening on port " << iPort << endl; + } catch (const std::exception&e) + { + cout << "Error: " << e.what() << endl; + return false; + } + return true; +} + void Install(const fs::path &programPrefix, const std::string endpointAddress) { cout << "Configuring pipedal" << endl; @@ -1000,14 +1105,14 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress) { throw std::runtime_error("Invalid endpoint address: " + endpointAddress); } - uint16_t port; + uint16_t port = 80; auto strPort = endpointAddress.substr(endpos + 1); try { auto lport = std::stoul(strPort); if (lport == 0 || lport >= std::numeric_limits::max()) { - throw std::runtime_error("out of range."); + throw std::runtime_error("Port number is too large."); } port = (uint16_t)lport; std::stringstream s; @@ -1020,6 +1125,7 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress) s << "Invalid port number: " << strPort; throw std::runtime_error(s.str()); } + PrepareServiceConfigurationFile(port); bool authBindRequired = port < 512; @@ -1188,9 +1294,18 @@ void Install(const fs::path &programPrefix, const std::string endpointAddress) { // don't allow abnormal termination, which leaves the package in a state that's // difficult to uninstall. - cout << "Error: " << e.what(); + cout << "Error: " << e.what() << endl; cout << " Run 'pipedalconfig --install' again to complete setup of PiPedal." << endl; } + const std::string ADDR_ANY = "0.0.0.0:"; + + if (endpointAddress.starts_with(ADDR_ANY)) + { + cout << "PiPedal web server is listening on port " << endpointAddress.substr(ADDR_ANY.length()) << endl; + } else { + cout << "PiPedal web server is listening on port " << endpointAddress << endl; + } + } static std::string GetCurrentWebServicePort() @@ -1199,7 +1314,7 @@ static std::string GetCurrentWebServicePort() config.Load("/etc/pipedal/config", ""); std::ostringstream ss; - ss << config.GetSocketServerPort(); + ss << config.GetSocketServerAddress() << ":" << config.GetSocketServerPort(); return ss.str(); } @@ -1208,7 +1323,7 @@ static void PrintHelp() PrettyPrinter pp; pp << "pipedalconfig - Command-line post-install configuration for PiPedal" << "\n" - << "Copyright (c) 2022-2024 Robin Davies." + << "Copyright (c) 2022-2024 Robin E. R. Davies." << "\n" << "\n" << "See https://rerdavies.github.io/pipedal/Documentation.html for " @@ -1239,6 +1354,10 @@ static void PrintHelp() << "The --port option controls which TCP/IP port the web server uses." << "\n\n" + << HangingIndent() << " --port \t" + << "Set the TCP/IP port that the web server will use." + << "\n" + << HangingIndent() << " --uninstall\t" << "Remove installed services." << "\n" @@ -1401,6 +1520,29 @@ void ListValidCountryCodes() } } +static std::string ProcessPortOption(std::string portOption) +{ + if (portOption == "" || portOption == "0") // allow testing of port autodetect. + { + std::string t = GetCurrentWebServicePort(); + if (portOption != "0") {// allows easy debugging of port AutoSelectPort. + portOption = t; + } else { + portOption = ""; + } + if (portOption == "") + { + portOption = AutoSelectPort(); + } + } + std::string ADDR_ANY = "0.0.0.0:"; + + if (portOption.find(':') == string::npos) + { + portOption = ADDR_ANY + portOption; + } + return portOption; +} int main(int argc, char **argv) { @@ -1457,6 +1599,10 @@ int main(int argc, char **argv) uninstall + stop + start + enable + disable + enable_hotspot + disable_hotspot + restart + enable_p2p + disable_p2p + list_p2p_channels + fix_permissions + list_wifi_country_codes; + if (actionCount == 0 && portOption.length() != 0) + { + ++actionCount; + } if (actionCount > 1) { throw std::runtime_error("Please provide only one action."); @@ -1553,12 +1699,6 @@ int main(int argc, char **argv) { return ListP2PChannels(parser.Arguments()); } - if (portOption.size() != 0 && !install) - { - cout << "Error: -port option can only be specified with the -install option." - << "\n"; - exit(EXIT_FAILURE); - } auto uid = getuid(); if (uid != 0 && !nosudo) @@ -1568,6 +1708,12 @@ int main(int argc, char **argv) try { + if (portOption.length() != 0 && !install) + { + portOption = ProcessPortOption(portOption); + SetWebServerPort(portOption); + return EXIT_SUCCESS; + } if (fix_permissions) { FixPermissions(); @@ -1595,20 +1741,11 @@ int main(int argc, char **argv) } } - if (portOption == "") - { - portOption = GetCurrentWebServicePort(); - if (portOption == "") - { - portOption = "80"; - } - } - if (portOption.find(':') == string::npos) - { - portOption = "0.0.0.0:" + portOption; - } + portOption = ProcessPortOption(portOption); + Install(prefix, portOption); FileSystemSync(); + } catch (const std::exception &e) { diff --git a/src/Lv2PluginChangeMonitor.cpp b/src/Lv2PluginChangeMonitor.cpp index b4b57f3..ea27e4a 100644 --- a/src/Lv2PluginChangeMonitor.cpp +++ b/src/Lv2PluginChangeMonitor.cpp @@ -44,7 +44,7 @@ void Lv2PluginChangeMonitor::Shutdown() { terminateThread = true; uint64_t val = 1; - write(shutdown_eventfd,(void*)&val, sizeof(val)); + auto _ = write(shutdown_eventfd,(void*)&val, sizeof(val)); monitorThread->join(); monitorThread = nullptr; close(shutdown_eventfd); diff --git a/src/SchedulerPriority.cpp b/src/SchedulerPriority.cpp index dd17093..0eb5194 100644 --- a/src/SchedulerPriority.cpp +++ b/src/SchedulerPriority.cpp @@ -24,25 +24,22 @@ #include "ss.hpp" #include -#ifdef __linux__ -#include "unistd.h" // for nice()` -#endif +#include // for nice(). + using namespace pipedal; -static constexpr int EXPECTED_RT_THREAD_PRIORITY_MAX = 81; +static constexpr int EXPECTED_RT_THREAD_PRIORITY_MAX = 95; -static constexpr int RT_AUDIO_THREAD_PRIORITY = 80; -static constexpr int NICE_AUDIO_THREAD_PRIORITY = -19; +static constexpr int RT_AUDIO_THREAD_PRIORITY = 90; // one above pipewire. -static constexpr int RT_AUDIOSERVICE_THREAD_PRIORITY = 10; -static constexpr int NICE_AUDIOSERVICE_THREAD_PRIORITY = -17; +static constexpr int RT_AUDIOSERVICE_THREAD_PRIORITY = 85; // one above pipewire service thread -static constexpr int RT_LV2SCHEDULER_THREAD_PRIORITY = -1; -static constexpr int NICE_LV2SCHEDULER_THREAD_PRIORITY = 2; // nice(2): don't let plugins screw things up by pinning the CPU +static constexpr int RT_LV2SCHEDULER_THREAD_PRIORITY = 5; static constexpr int RT_WEBSERVER_THREAD_PRIORITY = -1; -static constexpr int NICE_WEBSERVER_THREAD_PRIORITY = -2; // don't get bogged down by UI threads. + +static constexpr int NICE_WEBSERVER_PROCESS_PRIORITY = -9; // above chrome renderer, below pipewire.. bool pipedal::IsRtPreemptKernel(SchedulerPriority priority) { @@ -71,7 +68,7 @@ bool pipedal::IsRtPreemptKernel(SchedulerPriority priority) #endif } -static void SetPriority(int realtimePriority, int nicePriority, const char *priorityName) +static void SetPriority(int realtimePriority, const char *priorityName) { if (realtimePriority != -1) @@ -79,12 +76,20 @@ static void SetPriority(int realtimePriority, int nicePriority, const char *prio int initialPriority = realtimePriority; int min = sched_get_priority_min(SCHED_RR); int max = sched_get_priority_max(SCHED_RR); + if (max > EXPECTED_RT_THREAD_PRIORITY_MAX) + { + max = EXPECTED_RT_THREAD_PRIORITY_MAX; + } if (realtimePriority > max) { realtimePriority = max + EXPECTED_RT_THREAD_PRIORITY_MAX-realtimePriority; } if (realtimePriority < min) { realtimePriority = min; } + if (realtimePriority < 1) + { + realtimePriority = 1; + } if (initialPriority != realtimePriority) { Lv2Log::warning( @@ -104,15 +109,9 @@ static void SetPriority(int realtimePriority, int nicePriority, const char *prio } else { - Lv2Log::debug(SS("Failed to set RT thread priority for " << priorityName << " (" << strerror(result) << ")")); + Lv2Log::warning(SS("Failed to set RT thread priority for " << priorityName << " (" << strerror(result) << ")")); } } - // If the RT scheduler isn't working, fall back to using NICE priority. - int result = nice(nicePriority); - if (result == -1) - { - Lv2Log::error(SS("Failed to set thread priority. (" << priorityName << ")")); - } } void pipedal::SetThreadPriority(SchedulerPriority priority) @@ -122,16 +121,27 @@ void pipedal::SetThreadPriority(SchedulerPriority priority) switch (priority) { case SchedulerPriority::RealtimeAudio: - SetPriority(RT_AUDIO_THREAD_PRIORITY, NICE_AUDIO_THREAD_PRIORITY, "RealtimeAudio"); + SetPriority(RT_AUDIO_THREAD_PRIORITY, "RealtimeAudio"); break; case SchedulerPriority::AudioService: - SetPriority(RT_AUDIOSERVICE_THREAD_PRIORITY, NICE_AUDIOSERVICE_THREAD_PRIORITY, "AudioService"); + SetPriority(RT_AUDIOSERVICE_THREAD_PRIORITY, "AudioService"); break; case SchedulerPriority::Lv2Scheduler: - SetPriority(RT_LV2SCHEDULER_THREAD_PRIORITY, NICE_LV2SCHEDULER_THREAD_PRIORITY, "Lv2Scheduler"); + SetPriority(RT_LV2SCHEDULER_THREAD_PRIORITY, "Lv2Scheduler"); break; case SchedulerPriority::WebServerThread: - SetPriority(RT_WEBSERVER_THREAD_PRIORITY, NICE_WEBSERVER_THREAD_PRIORITY, "Lv2Scheduler"); + { + // do this by boosting the process priority + int currentNiceValue = nice(0); + if (currentNiceValue != NICE_WEBSERVER_PROCESS_PRIORITY) + { + errno = 0; + int ret = nice(NICE_WEBSERVER_PROCESS_PRIORITY-currentNiceValue); + if (ret == -1 && errno != 0) { + Lv2Log::error("Failed to set process nice value."); + } + } + } break; default: Lv2Log::error("Invalid scheduler priority."); diff --git a/src/Worker.cpp b/src/Worker.cpp index 1f0361d..f94b72d 100644 --- a/src/Worker.cpp +++ b/src/Worker.cpp @@ -39,7 +39,6 @@ #include #include "Lv2Log.hpp" #include -#include // for nice( #include #include "util.hpp" #include "SchedulerPriority.hpp"