Ubuntu doens't have a CPU governor.

This commit is contained in:
Robin Davies
2024-11-11 19:31:43 -05:00
parent bd994031bd
commit 64062fbbd7
17 changed files with 161 additions and 88 deletions
+31 -28
View File
@@ -4,8 +4,11 @@ project(pipedal
DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi" DESCRIPTION "PiPedal Guitar Effect Pedal For Raspberry Pi"
HOMEPAGE_URL "https://rerdavies.github.io/pipedal" HOMEPAGE_URL "https://rerdavies.github.io/pipedal"
) )
EXECUTE_PROCESS( COMMAND dpkg --print-architecture COMMAND tr -d '\n' OUTPUT_VARIABLE DEBIAN_ARCHITECTURE )
set (DISPLAY_VERSION "PiPedal v1.3.66-Release") set (DISPLAY_VERSION "PiPedal v1.3.66-Release")
set (PACKAGE_ARCHITECTURE "arm64") set (PACKAGE_ARCHITECTURE ${DEBIAN_ARCHITECTURE})
set (CMAKE_INSTALL_PREFIX "/usr/") set (CMAKE_INSTALL_PREFIX "/usr/")
include(CTest) include(CTest)
@@ -28,16 +31,6 @@ add_subdirectory("src")
# install (TARGETS pipedal_nm_p2pd DESTINATION ${CMAKE_INSTALL_PREFIX}/sbin # install (TARGETS pipedal_nm_p2pd DESTINATION ${CMAKE_INSTALL_PREFIX}/sbin
# ) # )
# select LV2 source directory for the current build architecture
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
set(LV2_SOURCE_DIRECTORY ${PROJECT_SOURCE_DIR}/lv2/${CMAKE_SYSTEM_PROCESSOR}/ToobAmp.lv2)
if (NOT EXISTS ${LV2_SOURCE_DIRECTORY})
message(FATAL_ERROR "Lv2 Binaries for architecture '${CMAKE_SYSTEM_PROCESSOR}' have not been provisioned. See lv2/Readme.md")
endif()
# add_subdirectory("test")
# add_test(NAME Test COMMAND piddletest) # add_test(NAME Test COMMAND piddletest)
set (REACT_BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build/) set (REACT_BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build/)
@@ -73,22 +66,34 @@ install (
DESTINATION /etc/pipedal/config DESTINATION /etc/pipedal/config
) )
install (DIRECTORY ${LV2_SOURCE_DIRECTORY} message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
DESTINATION /usr/lib/lv2
)
install(CODE if ("${DEBIAN_ARCHITECTURE}" MATCHES "arm64")
[[
file(GET_RUNTIME_DEPENDENCIES # select LV2 source directory for the current build architecture
EXECUTABLES
${CMAKE_INSTALL_PREFIX}/sbin/pipedaladmind set(LV2_SOURCE_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lv2/${CMAKE_SYSTEM_PROCESSOR}/ToobAmp.lv2)
${CMAKE_INSTALL_PREFIX}/sbin/pipedald
${CMAKE_INSTALL_PREFIX}/sbin/pipedal_update install (DIRECTORY ${LV2_SOURCE_DIRECTORY}
#${CMAKE_INSTALL_PREFIX}/sbin/pipedal_nm_p2pd DESTINATION /usr/lib/lv2
#${CMAKE_INSTALL_PREFIX}/sbin/pipedal_p2pd
${CMAKE_INSTALL_PREFIX}/bin/pipedalconfig
) )
]] elseif("${DEBIAN_ARCHITECTURE}" MATCHES "amd64")
)
add_custom_target(extract_toobamp_lv2_files ALL
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lv2/x86_64/unpackArtifact.sh
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Extracting x64 ToobAmp components"
)
set(LV2_SOURCE_DIRECTORY ${PROJECT_SOURCE_DIR}/build/lv2_x64/pkg/usr/lib/lv2/ToobAmp.lv2)
install (DIRECTORY ${LV2_SOURCE_DIRECTORY}
DESTINATION /usr/lib/lv2
)
else()
message(FATAL_ERROR "Unknown/unsupported build architecture: ${DEBIAN_ARCHITECTURE}")
endif()
set(CPACK_GENERATOR "DEB") set(CPACK_GENERATOR "DEB")
@@ -99,9 +104,7 @@ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IoT guitar effect pedal for Raspberry Pi"
set(CPACK_DEBIAN_PACKAGE_SECTION sound) set(CPACK_DEBIAN_PACKAGE_SECTION sound)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
#set(CPACK_DEBIAN_PACKAGE_DEPENDS "jackd2, hostapd, dhcpcd, dnsmasq" )
set(CPACK_DEBIAN_PACKAGE_DEPENDS "lv2-dev, authbind, gpg" ) set(CPACK_DEBIAN_PACKAGE_DEPENDS "lv2-dev, authbind, gpg" )
#set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
set(CPACK_PACKAGING_INSTALL_PREFIX /usr) set(CPACK_PACKAGING_INSTALL_PREFIX /usr)
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
+9
View File
@@ -3,3 +3,12 @@ This folder contains pre-built binaries for an initial bundle of Lv2 plugins.
This arrangment is temporary, and is expected to go away, once a reliable distribution This arrangment is temporary, and is expected to go away, once a reliable distribution
of this project and the ToobAmp project via apt can be arranged. of this project and the ToobAmp project via apt can be arranged.
To update the arm64 binaries for ToobAmp, build the ToobAmp project, run `./install.sh` in the ToobAmp project directory,
and then run `./provisionLv2` in the pipedal root directory. This copies the ToobAmp binaries into the pipedal source tree.
The x86_64 binaries are, instead built from an artifact provided by the github CMake build action. Currently, these
binaries are built on an Ubuntu 24.04 LTS build runner. PiPedals's build runner should run on the same build runner
configuration. The CMake build process will unpack the artifact, and extract ToobAmp LV2 binaries into the build directory
where the debian package can pick them up.
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/bash
rm -rf build/lv2_x64
mkdir build/lv2_x64
mkdir build/lv2_x64/pkg
dpkg-deb -x lv2/x86_64/toobamp_*_amd64.deb build/lv2_x64/pkg
+2
View File
@@ -21,6 +21,7 @@
export default class GovernorSettings { export default class GovernorSettings {
deserialize(input: any) : GovernorSettings{ deserialize(input: any) : GovernorSettings{
this.hasGovernor = input.hasGovernor;
this.governors = input.governors; this.governors = input.governors;
this.governor = input.governor; this.governor = input.governor;
return this; return this;
@@ -29,6 +30,7 @@ export default class GovernorSettings {
{ {
return new GovernorSettings().deserialize(this); return new GovernorSettings().deserialize(this);
} }
hasGovernor: boolean = true;
governors: string[] = ["ondemand","performance"]; governors: string[] = ["ondemand","performance"];
governor: string = "performance"; governor: string = "performance";
+28 -28
View File
@@ -19,10 +19,10 @@
import React from 'react'; import React from 'react';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import {isDarkMode} from './DarkMode'; import { isDarkMode } from './DarkMode';
const RED_COLOR = isDarkMode()? "#F88":"#C00"; const RED_COLOR = isDarkMode() ? "#F88" : "#C00";
const GREEN_COLOR = isDarkMode()? "rgba(255,255,255,0.7)": "#666"; const GREEN_COLOR = isDarkMode() ? "rgba(255,255,255,0.7)" : "#666";
@@ -33,23 +33,18 @@ function cpuDisplay(cpu: number): string {
return cpu.toFixed(1) + "%"; return cpu.toFixed(1) + "%";
} }
function fmtCpuFreq(freq: number): string function fmtCpuFreq(freq: number): string {
{ if (freq >= 100000000) {
if (freq >= 100000000) return (freq / 1000000).toFixed(1) + " GHz";
{
return (freq/1000000).toFixed(1) + " GHz";
} }
if (freq >= 10000000) if (freq >= 10000000) {
{ return (freq / 1000000).toFixed(2) + " GHz";
return (freq/1000000).toFixed(2) + " GHz";
} }
if (freq >= 1000000) if (freq >= 1000000) {
{ return (freq / 1000000).toFixed(3) + " GHz";
return (freq/1000000).toFixed(3) + " GHz";
} }
if (freq >= 1000) if (freq >= 1000) {
{ return (freq / 1000).toFixed(3) + " MHz";
return (freq/1000).toFixed(3) + " MHz";
} }
return freq + " KHz"; return freq + " KHz";
} }
@@ -65,6 +60,7 @@ export default class JackHostStatus {
this.temperaturemC = input.temperaturemC; this.temperaturemC = input.temperaturemC;
this.cpuFreqMax = input.cpuFreqMax; this.cpuFreqMax = input.cpuFreqMax;
this.cpuFreqMin = input.cpuFreqMin; this.cpuFreqMin = input.cpuFreqMin;
this.hasCpuGovernor = input.hasCpuGovernor;
this.governor = input.governor; this.governor = input.governor;
return this; return this;
} }
@@ -80,6 +76,7 @@ export default class JackHostStatus {
temperaturemC: number = -1000000; temperaturemC: number = -1000000;
cpuFreqMax: number = 0; cpuFreqMax: number = 0;
cpuFreqMin: number = 0; cpuFreqMin: number = 0;
hasCpuGovernor: boolean = false;
governor: string = ""; governor: string = "";
static getCpuInfo(label: string, status?: JackHostStatus): React.ReactNode { static getCpuInfo(label: string, status?: JackHostStatus): React.ReactNode {
@@ -91,18 +88,21 @@ export default class JackHostStatus {
} }
return (<div style={{ whiteSpace: "nowrap" }}> return (<div style={{ whiteSpace: "nowrap" }}>
<Typography variant="caption" color="inherit">{label}</Typography> <Typography variant="caption" color="inherit">{label}</Typography>
<Typography variant="caption" color="inherit"> {(status.cpuFreqMin != 0 || status.cpuFreqMax != 0) &&
{ (
(status.cpuFreqMax === status.cpuFreqMin)? <Typography variant="caption" color="inherit">
( {
<span> {status.governor} {fmtCpuFreq(status.cpuFreqMax)} </span> (status.cpuFreqMax === status.cpuFreqMin) ?
) (
:( <span> {status.governor} {fmtCpuFreq(status.cpuFreqMax)} </span>
<span> {status.governor} {fmtCpuFreq(status.cpuFreqMax)}-{fmtCpuFreq(status.cpuFreqMax)} </span> )
: (
<span> {status.governor} {fmtCpuFreq(status.cpuFreqMax)}-{fmtCpuFreq(status.cpuFreqMax)} </span>
) )
} }
</Typography> </Typography>
)}
</div>); </div>);
+13
View File
@@ -28,6 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include "Ipv6Helpers.hpp" #include "Ipv6Helpers.hpp"
#include "CpuGovernor.hpp"
using namespace pipedal; using namespace pipedal;
@@ -143,6 +144,10 @@ void AdminClient::SetGovernorSettings(const std::string &settings)
{ {
throw PiPedalException("Can't use AdminClient when running interactively."); throw PiPedalException("Can't use AdminClient when running interactively.");
} }
if (!HasCpuGovernor())
{
return;
}
std::stringstream cmd; std::stringstream cmd;
cmd << "GovernorSettings "; cmd << "GovernorSettings ";
json_writer writer(cmd, true); json_writer writer(cmd, true);
@@ -161,6 +166,10 @@ void AdminClient::MonitorGovernor(const std::string &governor)
{ {
return; return;
} }
if (!HasCpuGovernor())
{
return;
}
std::stringstream cmd; std::stringstream cmd;
cmd << "MonitorGovernor "; cmd << "MonitorGovernor ";
json_writer writer(cmd, true); json_writer writer(cmd, true);
@@ -178,6 +187,10 @@ void AdminClient::UnmonitorGovernor()
{ {
return; return;
} }
if (!HasCpuGovernor())
{
return;
}
std::stringstream cmd; std::stringstream cmd;
cmd << "UnmonitorGovernor"; cmd << "UnmonitorGovernor";
cmd << '\n'; cmd << '\n';
+4 -4
View File
@@ -76,7 +76,7 @@ static int exec(const std::string &command)
if ((pid = fork()) == 0) if ((pid = fork()) == 0)
{ {
execv(argv[0], (char *const *)argv.data()); execv(argv[0], (char *const *)argv.data());
write(1,"!\n",2); auto _ = write(1,"!\n",2);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else else
@@ -84,7 +84,7 @@ static int exec(const std::string &command)
if (pid == -1) if (pid == -1)
{ {
write(1,"*",1); auto _ = write(1,"*",1);
perror("execv"); perror("execv");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -99,8 +99,8 @@ static int exec(const std::string &command)
void updateLog(const std::string &message) void updateLog(const std::string &message)
{ {
write(1,message.c_str(),message.length()); auto _ = write(1,message.c_str(),message.length());
write(1,"\n",1); _ = write(1,"\n",1);
} }
+16 -1
View File
@@ -63,6 +63,10 @@ public:
void Start(std::string governor) void Start(std::string governor)
{ {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
if (!HasCpuGovernor())
{
return;
}
if (!pThread) if (!pThread)
{ {
this->governor = governor; this->governor = governor;
@@ -81,6 +85,10 @@ public:
} }
void Stop() void Stop()
{ {
if (!HasCpuGovernor())
{
return;
}
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
if (pThread) if (pThread)
{ {
@@ -109,6 +117,10 @@ private:
std::string savedGovernor; std::string savedGovernor;
void ServiceProc() void ServiceProc()
{ {
if (!HasCpuGovernor())
{
return;
}
savedGovernor = pipedal::GetCpuGovernor(); savedGovernor = pipedal::GetCpuGovernor();
pipedal::SetCpuGovernor(this->governor); pipedal::SetCpuGovernor(this->governor);
while (true) while (true)
@@ -303,7 +315,10 @@ private:
{ {
throw PiPedalArgumentException("Invalid arguments."); throw PiPedalArgumentException("Invalid arguments.");
} }
governorMonitorThread.SetGovernor(governor); if (HasCpuGovernor())
{
governorMonitorThread.SetGovernor(governor);
}
result = 0; result = 0;
} }
else if (command == "WifiConfigSettings") else if (command == "WifiConfigSettings")
+10 -3
View File
@@ -101,8 +101,8 @@ static void GetCpuFrequency(uint64_t *freqMin, uint64_t *freqMax)
catch (const std::exception &) catch (const std::exception &)
{ {
} }
if (fMin == 0) if (fMax == 0)
fMax = 0; fMin = 0;
*freqMin = fMin; *freqMin = fMin;
*freqMax = fMax; *freqMax = fMax;
} }
@@ -2091,7 +2091,13 @@ public:
result.cpuUsage_ = audioDriver->CpuUse(); result.cpuUsage_ = audioDriver->CpuUse();
} }
GetCpuFrequency(&result.cpuFreqMax_, &result.cpuFreqMin_); GetCpuFrequency(&result.cpuFreqMax_, &result.cpuFreqMin_);
result.governor_ = GetGovernor(); result.hasCpuGovernor_ = HasCpuGovernor();
if (result.hasCpuGovernor_)
{
result.governor_ = GetGovernor();
} else {
result.governor_ = "";
}
return result; return result;
} }
@@ -2278,5 +2284,6 @@ JSON_MAP_REFERENCE(JackHostStatus, msSinceLastUnderrun)
JSON_MAP_REFERENCE(JackHostStatus, temperaturemC) JSON_MAP_REFERENCE(JackHostStatus, temperaturemC)
JSON_MAP_REFERENCE(JackHostStatus, cpuFreqMin) JSON_MAP_REFERENCE(JackHostStatus, cpuFreqMin)
JSON_MAP_REFERENCE(JackHostStatus, cpuFreqMax) JSON_MAP_REFERENCE(JackHostStatus, cpuFreqMax)
JSON_MAP_REFERENCE(JackHostStatus, hasCpuGovernor)
JSON_MAP_REFERENCE(JackHostStatus, governor) JSON_MAP_REFERENCE(JackHostStatus, governor)
JSON_MAP_END() JSON_MAP_END()
+1
View File
@@ -184,6 +184,7 @@ namespace pipedal
int32_t temperaturemC_ = -100000; int32_t temperaturemC_ = -100000;
uint64_t cpuFreqMax_ = 0; uint64_t cpuFreqMax_ = 0;
uint64_t cpuFreqMin_ = 0; uint64_t cpuFreqMin_ = 0;
bool hasCpuGovernor_ = true;
std::string governor_; std::string governor_;
DECLARE_JSON_MAP(JackHostStatus); DECLARE_JSON_MAP(JackHostStatus);
+4 -2
View File
@@ -737,14 +737,16 @@ set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
# generate Copyright section of settings page. # generate Copyright section of settings page.
# warning: there may be multiple versions. Pick the latest. # warning: there may be multiple versions. Pick the latest.
if(EXISTS "/usr/share/doc/libboost1.74-dev") if(EXISTS "/usr/share/doc/libboost1.83-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.83-dev")
elseif(EXISTS "/usr/share/doc/libboost1.74-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.74-dev") set (BOOST_COPYRIGHT_DIR "libboost1.74-dev")
elseif(EXISTS "/usr/share/doc/libboost1.71-dev") elseif(EXISTS "/usr/share/doc/libboost1.71-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.71-dev") set (BOOST_COPYRIGHT_DIR "libboost1.71-dev")
elseif(EXISTS "/usr/share/doc/libboost1.67-dev") elseif(EXISTS "/usr/share/doc/libboost1.67-dev")
set (BOOST_COPYRIGHT_DIR "libboost1.67-dev") set (BOOST_COPYRIGHT_DIR "libboost1.67-dev")
else() else()
message(ERROR "Boost libary version has changed. Please update me.") message(FATAL_ERROR "Boost libary version has changed. Please update me.")
endif() endif()
+24 -16
View File
@@ -26,26 +26,34 @@
using namespace pipedal; using namespace pipedal;
#ifdef __WIN32__
// not a feature on Win32.
void pipedal::SetCpuGovernor(const std::string &governor) { }
std::vector<std::string> pipedal::GetAvailableGovernors() { return std::vector<std::string>(); }
#else
static const int SYSFS_RETRIES = 3; static const int SYSFS_RETRIES = 3;
bool pipedal::HasCpuGovernor()
{
#ifdef __WIN32__
return false;
#else
std::filesystem::path sysFsPath = SS("/sys/devices/system/cpu/cpu" << 0 << "/cpufreq/scaling_governor");
return std::filesystem::exists(sysFsPath);
#endif
}
std::string pipedal::GetCpuGovernor() std::string pipedal::GetCpuGovernor()
{ {
std::string result; std::string result;
try { try {
std::ifstream f("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"); std::ifstream f("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
if (!f.is_open())
{
return "";
}
f >> result; f >> result;
} catch (const std::exception &) } catch (const std::exception &)
{ {
return result;
} }
return result; return result;
@@ -115,6 +123,10 @@ void pipedal::SetCpuGovernor(const std::string &governor) {
break; break;
std::filesystem::path sysFsPath = SS("/sys/devices/system/cpu/cpu" << nCpu << "/cpufreq/scaling_governor"); std::filesystem::path sysFsPath = SS("/sys/devices/system/cpu/cpu" << nCpu << "/cpufreq/scaling_governor");
if (!std::filesystem::exists(sysFsPath))
{
return;
}
if (!writeAndVerify(sysFsPath,governor)) if (!writeAndVerify(sysFsPath,governor))
{ {
@@ -125,17 +137,13 @@ void pipedal::SetCpuGovernor(const std::string &governor) {
} }
} }
std::vector<std::string> pipedal::GetAvailableGovernors() { std::vector<std::string> pipedal::GetAvailableGovernors() {
if (!HasCpuGovernor())
{
return std::vector<std::string>();
}
return std::vector<std::string> { return std::vector<std::string> {
"performance", "performance",
"ondemand", "ondemand",
"powersave" "powersave"
}; };
} }
#endif
void SetCpuGovernor(const std::string &governor);
std::vector<std::string> GetAvailableGovernors();
+1
View File
@@ -23,6 +23,7 @@
#include <vector> #include <vector>
namespace pipedal { namespace pipedal {
bool HasCpuGovernor();
std::string GetCpuGovernor(); std::string GetCpuGovernor();
void SetCpuGovernor(const std::string &governor); void SetCpuGovernor(const std::string &governor);
+4 -3
View File
@@ -50,6 +50,7 @@ namespace fs = std::filesystem;
#include "GithubResponseHeaders.hpp" #include "GithubResponseHeaders.hpp"
class pipedal::UpdaterImpl : public Updater class pipedal::UpdaterImpl : public Updater
{ {
public: public:
@@ -236,7 +237,7 @@ void UpdaterImpl::Stop()
if (event_writer != -1) if (event_writer != -1)
{ {
uint64_t value = CLOSE_EVENT; uint64_t value = CLOSE_EVENT;
write(this->event_writer, &value, sizeof(uint64_t)); auto _ = write(this->event_writer, &value, sizeof(uint64_t));
} }
if (thread) if (thread)
{ {
@@ -256,7 +257,7 @@ void UpdaterImpl::Stop()
void UpdaterImpl::CheckNow() void UpdaterImpl::CheckNow()
{ {
uint64_t value = CHECK_NOW_EVENT; uint64_t value = CHECK_NOW_EVENT;
write(this->event_writer, &value, sizeof(uint64_t)); auto _ = write(this->event_writer, &value, sizeof(uint64_t));
} }
void UpdaterImpl::SetUpdateListener(UpdateListener &&listener) void UpdaterImpl::SetUpdateListener(UpdateListener &&listener)
@@ -912,7 +913,7 @@ void UpdaterImpl::SetUpdatePolicy(UpdatePolicyT updatePolicy)
void UpdaterImpl::ForceUpdateCheck() void UpdaterImpl::ForceUpdateCheck()
{ {
uint64_t value = UNCACHED_CHECK_NOW_EVENT; uint64_t value = UNCACHED_CHECK_NOW_EVENT;
write(this->event_writer, &value, sizeof(uint64_t)); auto _ = write(this->event_writer, &value, sizeof(uint64_t));
} }
UpdateStatus::UpdateStatus() UpdateStatus::UpdateStatus()
+1 -1
View File
@@ -97,7 +97,7 @@ void segvHandler(int sig) {
// Print out all the frames to stderr // Print out all the frames to stderr
const char *message = "Error: SEGV signal received.\n"; const char *message = "Error: SEGV signal received.\n";
write(STDERR_FILENO,message,strlen(message)); auto _ = write(STDERR_FILENO,message,strlen(message));
backtrace_symbols_fd(array+2, size-2, STDERR_FILENO); backtrace_symbols_fd(array+2, size-2, STDERR_FILENO);
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
+6 -2
View File
@@ -14,6 +14,7 @@
#include "TemporaryFile.hpp" #include "TemporaryFile.hpp"
#include "json_variant.hpp" #include "json_variant.hpp"
#include "GithubResponseHeaders.hpp" #include "GithubResponseHeaders.hpp"
#include "Finally.hpp"
using namespace std; using namespace std;
using namespace pipedal; using namespace pipedal;
@@ -37,12 +38,15 @@ std::string psystem(const std::string &command)
std::string cmdRedirected = command + " 2>&1"; std::string cmdRedirected = command + " 2>&1";
std::array<char, 128> buffer; std::array<char, 128> buffer;
std::string result; std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmdRedirected.c_str(), "r"), pclose); FILE *pipe = popen(cmdRedirected.c_str(), "r");
if (!pipe) if (!pipe)
{ {
throw std::runtime_error("popen() failed!"); throw std::runtime_error("popen() failed!");
} }
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) Finally ([pipe]() {
pclose(pipe);
});
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
{ {
result += buffer.data(); result += buffer.data();
} }