From c198859cd5219cc8c105aa78d015a2ddfbcc120c Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Thu, 3 Dec 2020 15:12:59 +0100 Subject: [PATCH 01/15] fix(menu): Wrong printf token in error message (#2264) 'level' is a string, not an integer --- src/modules/menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/menu.cpp b/src/modules/menu.cpp index dbf9adea..714bc464 100644 --- a/src/modules/menu.cpp +++ b/src/modules/menu.cpp @@ -140,7 +140,7 @@ namespace modules { m_log.info("%s: Opening menu level '%i'", name(), static_cast(m_level)); if (static_cast(m_level) >= m_levels.size()) { - m_log.warn("%s: Cannot open unexisting menu level '%i'", name(), level); + m_log.warn("%s: Cannot open unexisting menu level '%s'", name(), level); m_level = -1; } } else if (action == EVENT_CLOSE) { From 3d6a7ffd4dc4f06623d44d552cd82edeb4e1692e Mon Sep 17 00:00:00 2001 From: Vlad Glagolev Date: Fri, 4 Dec 2020 16:07:12 -0800 Subject: [PATCH 02/15] Fix linking when built with clang++ 3.4 (#2270) --- include/modules/meta/base.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/modules/meta/base.inl b/include/modules/meta/base.inl index 5e713cd1..6792c02f 100644 --- a/include/modules/meta/base.inl +++ b/include/modules/meta/base.inl @@ -48,7 +48,7 @@ namespace modules { template string module::type() const { - return string(CONST_MOD(Impl).TYPE); + return string(module::TYPE); } template From b2c515c73cb68e12740a56810113cc25461ab266 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Sat, 5 Dec 2020 02:48:18 +0100 Subject: [PATCH 03/15] fix(config): Reintroduce multiple inheritance (#2271) Pre 3.5.0, any key starting with 'inherit' was treated as an inherit directive. This allowed for multiple inheritance even though it was never inteded in that way. 3.5.0 removed that bug/feature by doing a strict check against 'inherit' It seems people were relying on this behavior, so we are adding it back. However multiple inheritance with multiple keys is also deprecated in favor of the `inherit` key now supporting multiple space separated sections. This is because the config doesn't have a key order, but inheritance does depend on the order the different section keys are copied over (if multiple inherited sections define the same key). Fixes #2269 --- src/components/config.cpp | 60 +++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/components/config.cpp b/src/components/config.cpp index a47050be..a94aaee2 100644 --- a/src/components/config.cpp +++ b/src/components/config.cpp @@ -72,34 +72,58 @@ void config::warn_deprecated(const string& section, const string& key, string re * Look for sections set up to inherit from a base section * and copy the missing parameters * + * Multiple sections can be specified, separated by a space. + * * [sub/section] - * inherit = base/section + * inherit = section1 section2 */ void config::copy_inherited() { for (auto&& section : m_sections) { + std::vector inherit_sections; + + // Collect all sections to be inherited for (auto&& param : section.second) { - if (param.first == "inherit") { - // Get name of base section + string key_name = param.first; + if (key_name == "inherit") { auto inherit = param.second; - if ((inherit = dereference(section.first, param.first, inherit, inherit)).empty()) { - throw value_error("Invalid section \"\" defined for \"" + section.first + ".inherit\""); + inherit = dereference(section.first, key_name, inherit, inherit); + + std::vector sections = string_util::split(std::move(inherit), ' '); + + inherit_sections.insert(inherit_sections.end(), sections.begin(), sections.end()); + + } else if (key_name.find("inherit") == 0) { + // Legacy support for keys that just start with 'inherit' + m_log.warn( + "\"%s.%s\": Using anything other than 'inherit' for inheriting section keys is deprecated. " + "The 'inherit' key supports multiple section names separated by a space.", + section.first, key_name); + + auto inherit = param.second; + inherit = dereference(section.first, key_name, inherit, inherit); + if (inherit.empty() || m_sections.find(inherit) == m_sections.end()) { + throw value_error( + "Invalid section \"" + inherit + "\" defined for \"" + section.first + "." + key_name + "\""); } - // Find and validate base section - auto base_section = m_sections.find(inherit); - if (base_section == m_sections.end()) { - throw value_error("Invalid section \"" + inherit + "\" defined for \"" + section.first + ".inherit\""); - } + inherit_sections.push_back(std::move(inherit)); + } + } - m_log.trace("config: Copying missing params (sub=\"%s\", base=\"%s\")", section.first, inherit); + for (const auto& base_name : inherit_sections) { + const auto base_section = m_sections.find(base_name); + if (base_section == m_sections.end()) { + throw value_error("Invalid section \"" + base_name + "\" defined for \"" + section.first + ".inherit\""); + } - /* - * Iterate the base and copy the parameters that haven't been defined - * for the sub-section - */ - for (auto&& base_param : base_section->second) { - section.second.emplace(base_param.first, base_param.second); - } + m_log.trace("config: Inheriting keys from \"%s\" in \"%s\"", base_name, section.first); + + /* + * Iterate the base and copy the parameters that haven't been defined + * yet. + */ + for (auto&& base_param : base_section->second) { + section.second.emplace(base_param.first, base_param.second); } } } From 82ebad5e7a1bada94ce4e93f43bbd67d71e778c0 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Sat, 5 Dec 2020 22:58:38 +0100 Subject: [PATCH 04/15] fix(timer_module): Ensure that interval > 0 (#2274) Since 3.5.0, we use m_interval for a modulo operation, this crashes the bar if the interval is 0. A non-positive interval shouldn't be allowed anyway, so we now throw an exception in that case. Fixes #2273 --- include/modules/meta/timer_module.hpp | 14 ++++++++++++++ src/modules/counter.cpp | 4 ++-- src/modules/cpu.cpp | 2 +- src/modules/date.cpp | 2 +- src/modules/fs.cpp | 2 +- src/modules/github.cpp | 2 +- src/modules/memory.cpp | 2 +- src/modules/network.cpp | 2 +- src/modules/temperature.cpp | 2 +- 9 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/modules/meta/timer_module.hpp b/include/modules/meta/timer_module.hpp index d4f1a4a2..2cd5f3bf 100644 --- a/include/modules/meta/timer_module.hpp +++ b/include/modules/meta/timer_module.hpp @@ -17,6 +17,20 @@ namespace modules { } protected: + /** + * Loads and sets the interval for this module. + * + * Will throw an exception if a non-positive (<= 0) number is given. + */ + void set_interval(interval_t def) { + m_interval = this->m_conf.template get(this->name(), "interval", def); + + if (m_interval <= 0s) { + throw module_error( + this->name() + ": 'interval' must be larger than 0 (got '" + to_string(m_interval.count()) + "s')"); + } + } + void runner() { this->m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id())); diff --git a/src/modules/counter.cpp b/src/modules/counter.cpp index 25c7ae9e..3abd5e40 100644 --- a/src/modules/counter.cpp +++ b/src/modules/counter.cpp @@ -9,7 +9,7 @@ namespace modules { counter_module::counter_module(const bar_settings& bar, string name_) : timer_module(bar, move(name_)) { - m_interval = m_conf.get(name(), "interval", m_interval); + set_interval(1s); m_formatter->add(DEFAULT_FORMAT, TAG_COUNTER, {TAG_COUNTER}); } @@ -25,6 +25,6 @@ namespace modules { } return false; } -} +} // namespace modules POLYBAR_NS_END diff --git a/src/modules/cpu.cpp b/src/modules/cpu.cpp index 78686a2d..3e3363df 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -16,7 +16,7 @@ namespace modules { template class module; cpu_module::cpu_module(const bar_settings& bar, string name_) : timer_module(bar, move(name_)) { - m_interval = m_conf.get(name(), "interval", 1s); + set_interval(1s); m_ramp_padding = m_conf.get(name(), "ramp-coreload-spacing", 1); diff --git a/src/modules/date.cpp b/src/modules/date.cpp index 127e7832..5bb4b6b0 100644 --- a/src/modules/date.cpp +++ b/src/modules/date.cpp @@ -22,7 +22,7 @@ namespace modules { throw module_error("No date or time format specified"); } - m_interval = m_conf.get(name(), "interval", 1s); + set_interval(1s); m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_DATE}); diff --git a/src/modules/fs.cpp b/src/modules/fs.cpp index ad0f8820..ed1cc677 100644 --- a/src/modules/fs.cpp +++ b/src/modules/fs.cpp @@ -30,7 +30,7 @@ namespace modules { m_remove_unmounted = m_conf.get(name(), "remove-unmounted", m_remove_unmounted); m_fixed = m_conf.get(name(), "fixed-values", m_fixed); m_spacing = m_conf.get(name(), "spacing", m_spacing); - m_interval = m_conf.get(name(), "interval", 30s); + set_interval(30s); // Add formats and elements m_formatter->add( diff --git a/src/modules/github.cpp b/src/modules/github.cpp index 29ef5d1c..f40b15ac 100644 --- a/src/modules/github.cpp +++ b/src/modules/github.cpp @@ -23,7 +23,7 @@ namespace modules { m_api_url += '/'; } - m_interval = m_conf.get(name(), "interval", 60s); + set_interval(60s); m_empty_notifications = m_conf.get(name(), "empty-notifications", m_empty_notifications); m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL}); diff --git a/src/modules/memory.cpp b/src/modules/memory.cpp index c07c06fc..5882da0f 100644 --- a/src/modules/memory.cpp +++ b/src/modules/memory.cpp @@ -16,7 +16,7 @@ namespace modules { template class module; memory_module::memory_module(const bar_settings& bar, string name_) : timer_module(bar, move(name_)) { - m_interval = m_conf.get(name(), "interval", 1s); + set_interval(1s); m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR_USED, TAG_BAR_FREE, TAG_RAMP_USED, TAG_RAMP_FREE, TAG_BAR_SWAP_USED, TAG_BAR_SWAP_FREE, TAG_RAMP_SWAP_USED, TAG_RAMP_SWAP_FREE}); diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 21138777..cf7d2bd3 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -19,7 +19,7 @@ namespace modules { m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update); m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth); m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate); - m_interval = m_conf.get(name(), "interval", 1s); + set_interval(1s); m_unknown_up = m_conf.get(name(), "unknown-as-up", false); m_conf.warn_deprecated(name(), "udspeed-minwidth", "%downspeed:min:max% and %upspeed:min:max%"); diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index 8d2a50ca..98b195e5 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -19,7 +19,7 @@ namespace modules { m_path = m_conf.get(name(), "hwmon-path", ""s); m_tempbase = m_conf.get(name(), "base-temperature", 0); m_tempwarn = m_conf.get(name(), "warn-temperature", 80); - m_interval = m_conf.get(name(), "interval", 1s); + set_interval(1s); m_units = m_conf.get(name(), "units", m_units); if (m_path.empty()) { From 037f6e6c4522e4504ab56e8f393a1c2f1b15f874 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Sat, 5 Dec 2020 23:28:48 +0100 Subject: [PATCH 05/15] fix(xworkspaces): Never swallow updates (#2275) If two WM events arrive withing 25ms of one-another, the second one does not trigger a bar update. The module state is still correct, it is just not reflected in the bar. This somehow caused updates being swallowed in fluxbox, but only after PR #882 was merged, even though that 25ms restriction existed long before that. Fixes #2272 --- include/modules/xworkspaces.hpp | 2 -- src/modules/xworkspaces.cpp | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/modules/xworkspaces.hpp b/include/modules/xworkspaces.hpp index 62aafd90..d58cf455 100644 --- a/include/modules/xworkspaces.hpp +++ b/include/modules/xworkspaces.hpp @@ -110,8 +110,6 @@ namespace modules { // The following mutex is here to protect the data of this modules. // This can't be achieved using m_buildlock since we "CRTP override" get_output(). mutable mutex m_workspace_mutex; - - event_timer m_timer{0L, 25L}; }; } // namespace modules diff --git a/src/modules/xworkspaces.cpp b/src/modules/xworkspaces.cpp index 128524fd..f8b7b9b1 100644 --- a/src/modules/xworkspaces.cpp +++ b/src/modules/xworkspaces.cpp @@ -126,9 +126,7 @@ namespace modules { return; } - if (m_timer.allow(evt->time)) { - broadcast(); - } + broadcast(); } /** From f6231f351feacc0f18b0972038d5a9bba3ca3fcd Mon Sep 17 00:00:00 2001 From: Vlad Glagolev Date: Fri, 11 Dec 2020 16:07:13 -0800 Subject: [PATCH 06/15] Add missing header (#2280) --- include/utils/process.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/utils/process.hpp b/include/utils/process.hpp index eb380532..72b21015 100644 --- a/include/utils/process.hpp +++ b/include/utils/process.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "common.hpp" POLYBAR_NS From d66563448446a2daaaeb6a960e51a6aebb3f5193 Mon Sep 17 00:00:00 2001 From: Vlad Glagolev Date: Fri, 11 Dec 2020 16:07:51 -0800 Subject: [PATCH 07/15] Fix build with clang++ 3.4 (#2279) --- include/adapters/pulseaudio.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/adapters/pulseaudio.hpp b/include/adapters/pulseaudio.hpp index 39eceb66..09398ac1 100644 --- a/include/adapters/pulseaudio.hpp +++ b/include/adapters/pulseaudio.hpp @@ -63,7 +63,7 @@ class pulseaudio { pa_cvolume cv; bool muted{false}; // default sink name - static constexpr auto DEFAULT_SINK{"@DEFAULT_SINK@"}; + static constexpr auto DEFAULT_SINK = "@DEFAULT_SINK@"; pa_context* m_context{nullptr}; pa_threaded_mainloop* m_mainloop{nullptr}; From a45b5d042453b9ed5b0fb3d96108573e0124ba6c Mon Sep 17 00:00:00 2001 From: patrick96 Date: Fri, 11 Dec 2020 22:10:20 +0100 Subject: [PATCH 08/15] fix(build): UB when converting strings in logger The memory returned was no longer valid because arg is destructed after the function returns. --- include/components/logger.hpp | 2 +- src/components/logger.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/components/logger.hpp b/include/components/logger.hpp index 5c7d1ba2..0d270927 100644 --- a/include/components/logger.hpp +++ b/include/components/logger.hpp @@ -100,7 +100,7 @@ class logger { /** * Convert string */ - const char* convert(string arg) const; // NOLINT + const char* convert(const string& arg) const; /** * Convert thread id diff --git a/src/components/logger.cpp b/src/components/logger.cpp index f482eeaf..f1e968c8 100644 --- a/src/components/logger.cpp +++ b/src/components/logger.cpp @@ -1,6 +1,7 @@ +#include "components/logger.hpp" + #include -#include "components/logger.hpp" #include "errors.hpp" #include "settings.hpp" #include "utils/concurrency.hpp" @@ -12,7 +13,7 @@ POLYBAR_NS /** * Convert string */ -const char* logger::convert(string arg) const { // NOLINT +const char* logger::convert(const string& arg) const { return arg.c_str(); } From 54e2490aa5e1429329ef340347c56f8904bc60b2 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 00:20:04 +0100 Subject: [PATCH 09/15] fix(logger): Wrong conversion function called For some reason when passing some non-const strings to convert, the convert(T&& arg) method was used instead of the one specialized for strings. This caused an error in clang because you can't pass objects with non-trivial types to varargs functions. The best solution I found was to just add a specialized function for non-const strings. --- include/components/logger.hpp | 1 + src/components/logger.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/components/logger.hpp b/include/components/logger.hpp index 0d270927..6d995072 100644 --- a/include/components/logger.hpp +++ b/include/components/logger.hpp @@ -100,6 +100,7 @@ class logger { /** * Convert string */ + const char* convert(string& arg) const; const char* convert(const string& arg) const; /** diff --git a/src/components/logger.cpp b/src/components/logger.cpp index f1e968c8..f5151799 100644 --- a/src/components/logger.cpp +++ b/src/components/logger.cpp @@ -13,6 +13,10 @@ POLYBAR_NS /** * Convert string */ +const char* logger::convert(string& arg) const { + return arg.c_str(); +} + const char* logger::convert(const string& arg) const { return arg.c_str(); } From cf739ed29548e8aa9e67ab7dbbee2bd1b8efb017 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Fri, 11 Dec 2020 21:37:54 +0100 Subject: [PATCH 10/15] ci: Use github actions --- .github/workflows/ci.yml | 88 ++++++++++++++++++++++++++++++++++++++ .travis.yml | 8 ++-- README.md | 1 + common/ci/configure.sh | 46 ++++++++++++++++++++ common/ci/summary.sh | 19 ++++++++ common/travis/build.sh | 3 -- common/travis/configure.sh | 32 -------------- common/travis/summary.sh | 13 ------ 8 files changed, 158 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100755 common/ci/configure.sh create mode 100755 common/ci/summary.sh delete mode 100755 common/travis/build.sh delete mode 100755 common/travis/configure.sh delete mode 100755 common/travis/summary.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..8d853338 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,88 @@ +name: CI +on: [push, pull_request] + +jobs: + docs: + runs-on: ubuntu-20.04 + env: + COLOR: "ON" + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install -y python3-sphinx + - name: Build Documentation + run: | + mkdir -p doc/build + cd doc/build + cmake .. + make doc + + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + cxx: [g++, clang++] + polybar_build_type: ["full"] + build_type: ["Release"] + include: + - cxx: g++ + polybar_build_type: "tests" + build_type: "Coverage" + - cxx: g++ + polybar_build_type: "minimal" + build_type: "Release" + env: + CXX: ${{ matrix.cxx }} + BUILD_TYPE: ${{ matrix.build_type }} + POLYBAR_BUILD_TYPE: ${{ matrix.polybar_build_type }} + POLYBAR_DIR: ${{ github.workspace }} + BUILD_DIR: "${{ github.workspace}}/build" + MAKEFLAGS: "-j4" + COLOR: "ON" + steps: + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libxcb-composite0-dev \ + libxcb-ewmh-dev \ + libxcb-icccm4-dev \ + libxcb-image0-dev \ + libxcb-randr0-dev \ + libxcb-util0-dev \ + libxcb1-dev \ + libcairo2-dev \ + python3-xcbgen \ + xcb-proto + + if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then + sudo apt-get install -y \ + libxcb-xkb-dev \ + libxcb-cursor-dev \ + libxcb-xrm-dev \ + i3-wm \ + libcurl4-openssl-dev \ + libjsoncpp-dev \ + libasound2-dev \ + libpulse-dev \ + libiw-dev \ + libmpdclient-dev + fi + - uses: actions/checkout@v2 + with: + submodules: true + - name: Summary + run: ./common/ci/summary.sh + - name: Configure + run: ./common/ci/configure.sh + - name: Build + run: | + cd $BUILD_DIR + make + - name: Tests + if: ${{ matrix.polybar_build_type == 'tests' }} + run: | + cd $BUILD_DIR + make check + cd $POLYBAR_DIR + bash <(curl -s https://codecov.io/bash) -F unittests -a "-ap" -Z diff --git a/.travis.yml b/.travis.yml index 5c4fd79c..6fc0927a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ addons: - libiw-dev - libmpdclient-dev -script: source ${TRAVIS_BUILD_DIR}/common/travis/build.sh +script: source ${TRAVIS_BUILD_DIR}/common/ci/build.sh matrix: include: @@ -59,7 +59,7 @@ matrix: addons: {apt: {packages: [*base_deps, *optional_deps]}} - compiler: gcc - env: BUILD_TYPE=Coverage POLYBAR_BUILD_TYPE=tests BUILD_TESTS=ON + env: BUILD_TYPE=Coverage POLYBAR_BUILD_TYPE=tests addons: {apt: {packages: [*base_deps, *optional_deps]}} script: make check after_success: @@ -82,8 +82,8 @@ cache: apt: true before_script: - - source ${TRAVIS_BUILD_DIR}/common/travis/summary.sh - - source ${TRAVIS_BUILD_DIR}/common/travis/configure.sh + - source ${TRAVIS_BUILD_DIR}/common/ci/summary.sh + - source ${TRAVIS_BUILD_DIR}/common/ci/configure.sh # Only fetch the newest 5 commits instead of 50 git: diff --git a/README.md b/README.md index 0ff03acc..1f36a658 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ A fast and easy-to-use tool for creating status bars.

+ diff --git a/common/ci/configure.sh b/common/ci/configure.sh new file mode 100755 index 00000000..90718748 --- /dev/null +++ b/common/ci/configure.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +set -eo pipefail + +if [ -d "$BUILD_DIR" ]; then + rm -Rf "$BUILD_DIR" +fi + +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then + ENABLE_PULSEAUDIO=ON + ENABLE_NETWORK=ON + ENABLE_MPD=ON + ENABLE_CURL=ON + ENABLE_ALSA=ON + ENABLE_I3=ON + WITH_XRM=ON + WITH_XKB=ON + WITH_XRANDR_MONITORS=ON + WITH_XCURSOR=ON +fi + +if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then + BUILD_TESTS=ON +fi + +cmake \ + -DCMAKE_CXX_COMPILER="${CXX}" \ + -DCMAKE_CXX_FLAGS="${CXXFLAGS} -Werror" \ + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ + -DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \ + -DBUILD_DOC:BOOL="${BUILD_DOC:-OFF}" \ + -DWITH_XRANDR=ON \ + -DENABLE_PULSEAUDIO="${ENABLE_PULSEAUDIO:-OFF}" \ + -DENABLE_NETWORK="${ENABLE_NETWORK:-OFF}" \ + -DENABLE_MPD="${ENABLE_MPD:-OFF}" \ + -DENABLE_CURL="${ENABLE_CURL:-OFF}" \ + -DENABLE_ALSA="${ENABLE_ALSA:-OFF}" \ + -DENABLE_I3="${ENABLE_I3:-OFF}" \ + -DWITH_XRM="${WITH_XRM:-OFF}" \ + -DWITH_XKB="${WITH_XKB:-OFF}" \ + -DWITH_XRANDR_MONITORS="${WITH_XRANDR_MONITORS:-OFF}" \ + -DWITH_XCURSOR="${WITH_XCURSOR:-OFF}" \ + .. diff --git a/common/ci/summary.sh b/common/ci/summary.sh new file mode 100755 index 00000000..a6bfcf82 --- /dev/null +++ b/common/ci/summary.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -eo pipefail + +set -x + +"${CXX}" --version +cmake --version + +set +x + +echo "PATH=${PATH}" +echo "CXX=${CXX}" +echo "CXXFLAGS=${CXXFLAGS}" +echo "LDFLAGS=${LDFLAGS}" +echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" +echo "MAKEFLAGS=${MAKEFLAGS}" +echo "POLYBAR_BUILD_TYPE=${POLYBAR_BUILD_TYPE}" +echo "CMAKE_BUILD_TYPE=${BUILD_TYPE}" diff --git a/common/travis/build.sh b/common/travis/build.sh deleted file mode 100755 index 9e376049..00000000 --- a/common/travis/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd "${TRAVIS_BUILD_DIR}/build" || false -make || exit $? diff --git a/common/travis/configure.sh b/common/travis/configure.sh deleted file mode 100755 index b67d78bd..00000000 --- a/common/travis/configure.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -mkdir -p "${TRAVIS_BUILD_DIR}/build" -cd "${TRAVIS_BUILD_DIR}/build" || false - -FLAGS="" - -# Disable all extra modules and X extensions for minimal builds -# Most of these should already be turned off because their libraries are not -# installed, but some may not be -if [ "$POLYBAR_BUILD_TYPE" == "minimal" ]; then - FLAGS=( - "-DENABLE_PULSEAUDIO=OFF" - "-DENABLE_NETWORK=OFF" - "-DENABLE_MPD=OFF" - "-DENABLE_CURL=OFF" - "-DENABLE_ALSA=OFF" - "-DENABLE_I3=OFF" - "-DWITH_XRM=OFF" - "-DWITH_XKB=OFF" - "-DWITH_XRANDR_MONITORS=OFF" - "-DWITH_XCURSOR=OFF" - "-DWITH_XRANDR=ON" - ) -fi - -cmake \ - -DCMAKE_CXX_COMPILER="${CXX}" \ - -DCMAKE_CXX_FLAGS="${CXXFLAGS} -Werror" \ - -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ - -DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \ - -DBUILD_DOC:BOOL="${BUILD_DOC:-OFF}" \ - "${FLAGS[@]}" .. diff --git a/common/travis/summary.sh b/common/travis/summary.sh deleted file mode 100755 index 708d6f7b..00000000 --- a/common/travis/summary.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -echo "${CXX} --version" -eval "${CXX} --version" - -echo "cmake --version" -cmake --version - -echo "PATH=${PATH}" -echo "CXX=${CXX}" -echo "CXXFLAGS=${CXXFLAGS}" -echo "LDFLAGS=${LDFLAGS}" -echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" -echo "JOBS=${JOBS}" From 95537f458d78c81f7515c9ca7ca84da69f219ade Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 01:15:49 +0100 Subject: [PATCH 11/15] ci: Add manual trigger --- .github/workflows/ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d853338..99746764 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,12 @@ name: CI -on: [push, pull_request] +on: + workflow_dispatch: + inputs: + ref: + description: 'ref' + required: false + push: + pull_request: jobs: docs: @@ -8,6 +15,8 @@ jobs: COLOR: "ON" steps: - uses: actions/checkout@v2 + with: + ref: ${{ github.event.inputs.ref }} - name: Install Dependencies run: sudo apt-get install -y python3-sphinx - name: Build Documentation @@ -71,6 +80,7 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + ref: ${{ github.event.inputs.ref }} - name: Summary run: ./common/ci/summary.sh - name: Configure From d6148e32887374255f6ca75a912cb4d3263fb7a6 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 01:33:47 +0100 Subject: [PATCH 12/15] Remove travis --- .travis.yml | 108 ---------------------------------------------------- README.md | 1 - 2 files changed, 109 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6fc0927a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,108 +0,0 @@ -sudo: required -dist: focal -language: cpp - -env: - global: - - JOBS=4 - - MAKEFLAGS="-j ${JOBS}" - - POLYBAR_BUILD_TYPE="compile" - -# Build configurations can either not specify anything for 'addon' and use this -# default list of packages. Or they can pick and choose which package groups to -# install -addons: - apt: - packages: - - &base_deps - - libxcb-composite0-dev - - libxcb-ewmh-dev - - libxcb-icccm4-dev - - libxcb-image0-dev - - libxcb-randr0-dev - - libxcb-util0-dev - - python3-xcbgen - - xcb-proto - - &optional_deps - - libxcb-xkb-dev - - libxcb-cursor-dev - - libxcb-xrm-dev - - libxcb1-dev - - xutils-dev - - i3-wm - - libjsoncpp-dev - - libasound2-dev - - libpulse-dev - - libcairo2-dev - - libiw-dev - - libmpdclient-dev - -script: source ${TRAVIS_BUILD_DIR}/common/ci/build.sh - -matrix: - include: - # Only builds the documentation - - language: generic - # Doesn't actually do anything, just used for the indicator on travis - compiler: Sphinx - addons: {apt: {packages: [python3-sphinx]}} - before_script: - - mkdir -p doc/build - - cd doc/build - - cmake .. - script: make doc - # Disable unnecessary commands - cache: - - - compiler: clang - env: BUILD_TYPE=Release - addons: {apt: {packages: [*base_deps, *optional_deps]}} - - - compiler: gcc - env: BUILD_TYPE=Coverage POLYBAR_BUILD_TYPE=tests - addons: {apt: {packages: [*base_deps, *optional_deps]}} - script: make check - after_success: - - cd ${TRAVIS_BUILD_DIR} - - bash <(curl -s https://codecov.io/bash) -F unittests -a "-ap" -Z || echo "Codecov did not collect coverage reports" - - - compiler: gcc - env: BUILD_TYPE=Release - addons: {apt: {packages: [*base_deps, *optional_deps]}} - - # Minimal build, contains no optional dependencies. This makes sure that - # we properly remove files from compilation that depend on libraries that - # are not installed - - compiler: gcc - env: BUILD_TYPE=Release POLYBAR_BUILD_TYPE=minimal - addons: {apt: {packages: [*base_deps]}} - -cache: - ccache: true - apt: true - -before_script: - - source ${TRAVIS_BUILD_DIR}/common/ci/summary.sh - - source ${TRAVIS_BUILD_DIR}/common/ci/configure.sh - -# Only fetch the newest 5 commits instead of 50 -git: - depth: 5 - -notifications: - email: false - irc: - channels: - - "irc.freenode.org#polybar" - template: - - " %{repository_slug}(%{branch})#%{build_number} | \"%{commit_subject}\" by %{author} | Commit #%{commit} %{result}: %{build_url}" - use_notice: true - on_success: change - on_failure: change - webhooks: - urls: - # For the https://gitter.im/polybar/polybar gitter room - - https://webhooks.gitter.im/e/10bdbe25961312646ace - on_success: change - on_failure: always - on_start: never diff --git a/README.md b/README.md index 1f36a658..974276cf 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,6 @@ A fast and easy-to-use tool for creating status bars.

- From ccf14d98169aa5306a745ea86d05300771501206 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 02:03:30 +0100 Subject: [PATCH 13/15] Fix CI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 974276cf..a1a67b7c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A fast and easy-to-use tool for creating status bars.

- + From 47483a94f1302746cae31bea789ced95bc9aeffe Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 02:21:36 +0100 Subject: [PATCH 14/15] fix(process): fork_detached created zombie processes Since the forked processes are still our children, we need to wait on them, otherwise they become zombie processes. We now fork twice, let the first fork immediately return and wait on it. This reparents the second fork, which runs the actual code, to the init process which then collects it. Ref #770 --- include/utils/process.hpp | 5 ++- src/utils/command.cpp | 2 +- src/utils/process.cpp | 63 ++++++++++++++++++++++++++---- tests/unit_tests/utils/process.cpp | 8 ++-- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/include/utils/process.hpp b/include/utils/process.hpp index 72b21015..3ab5fd7b 100644 --- a/include/utils/process.hpp +++ b/include/utils/process.hpp @@ -12,11 +12,14 @@ namespace process_util { void redirect_stdio_to_dev_null(); - pid_t fork_detached(std::function const& lambda); + pid_t spawn_async(std::function const& lambda); + void fork_detached(std::function const& lambda); void exec(char* cmd, char** args); void exec_sh(const char* cmd); + int wait(pid_t pid); + pid_t wait_for_completion(pid_t process_id, int* status_addr = nullptr, int waitflags = 0); pid_t wait_for_completion(int* status_addr, int waitflags = 0); pid_t wait_for_completion_nohang(pid_t process_id, int* status); diff --git a/src/utils/command.cpp b/src/utils/command.cpp index 2f2afc2c..7e8d3a9f 100644 --- a/src/utils/command.cpp +++ b/src/utils/command.cpp @@ -33,7 +33,7 @@ command::~command() { * Execute the command */ int command::exec(bool wait_for_completion) { - m_forkpid = process_util::fork_detached([m_cmd = m_cmd] { process_util::exec_sh(m_cmd.c_str()); }); + m_forkpid = process_util::spawn_async([m_cmd = m_cmd] { process_util::exec_sh(m_cmd.c_str()); }); if (wait_for_completion) { auto status = wait(); m_forkpid = -1; diff --git a/src/utils/process.cpp b/src/utils/process.cpp index f5ec0857..1127c606 100644 --- a/src/utils/process.cpp +++ b/src/utils/process.cpp @@ -45,15 +45,11 @@ namespace process_util { } /** - * Forks a child process and completely detaches it. + * Forks a child process and executes the given lambda function in it. * - * In the child process, the given lambda function is executed. - * - * Use this if you want to run a command and just forget about it. - * - * \returns The PID of the child process + * Processes spawned this way need to be waited on by the caller. */ - pid_t fork_detached(std::function const& lambda) { + pid_t spawn_async(std::function const& lambda) { pid_t pid = fork(); switch (pid) { case -1: @@ -71,6 +67,50 @@ namespace process_util { } } + /** + * Forks a child process and completely detaches it. + * + * In the child process, the given lambda function is executed. + * We fork twice so that the first forked process can exit and it's child is + * reparented to the init process. + * + * Ref: https://web.archive.org/web/20120914180018/http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16 + * + * Use this if you want to run a command and just forget about it. + * + * \returns The PID of the child process + */ + void fork_detached(std::function const& lambda) { + pid_t pid = fork(); + switch (pid) { + case -1: + throw runtime_error("fork_detached: Unable to fork: " + string(strerror(errno))); + case 0: + // Child + setsid(); + + pid = fork(); + switch (pid) { + case -1: + throw runtime_error("fork_detached: Unable to fork: " + string(strerror(errno))); + case 0: + // Child + umask(0); + redirect_stdio_to_dev_null(); + lambda(); + _Exit(0); + } + + _Exit(0); + default: + /* + * The first fork immediately exits and we have to collect its exit + * status + */ + wait(pid); + } + } + /** * Execute command */ @@ -92,6 +132,15 @@ namespace process_util { } } + int wait(pid_t pid) { + int forkstatus; + do { + process_util::wait_for_completion(pid, &forkstatus, WCONTINUED | WUNTRACED); + } while (!WIFEXITED(forkstatus) && !WIFSIGNALED(forkstatus)); + + return WEXITSTATUS(forkstatus); + } + /** * Wait for child process */ diff --git a/tests/unit_tests/utils/process.cpp b/tests/unit_tests/utils/process.cpp index cfd8351c..64ff21f6 100644 --- a/tests/unit_tests/utils/process.cpp +++ b/tests/unit_tests/utils/process.cpp @@ -12,8 +12,8 @@ using namespace polybar; using namespace process_util; -TEST(ForkDetached, is_detached) { - pid_t pid = fork_detached([] { exec_sh("sleep 0.1"); }); +TEST(SpawnAsync, is_async) { + pid_t pid = spawn_async([] { exec_sh("sleep 0.1"); }); int status; pid_t res = process_util::wait_for_completion_nohang(pid, &status); @@ -23,8 +23,8 @@ TEST(ForkDetached, is_detached) { EXPECT_FALSE(WIFEXITED(status)); } -TEST(ForkDetached, exit_code) { - pid_t pid = fork_detached([] { exec_sh("exit 42"); }); +TEST(SpawnAsync, exit_code) { + pid_t pid = spawn_async([] { exec_sh("exit 42"); }); int status = 0; pid_t res = waitpid(pid, &status, 0); From 9ba805d78fbb7b09da7570251ef230bdb257efda Mon Sep 17 00:00:00 2001 From: patrick96 Date: Sat, 12 Dec 2020 13:02:47 +0100 Subject: [PATCH 15/15] Release 3.5.1 Changelog **Features** * config: Multiple inheritance (#2271), see #2269 **Fixes** * (#2285), see #770, #2289 * Timer module: Polybar crash when interval is set to 0 (#2274), see #2273 * `custom/menu`: Wrong level numbers in error messages (#2264) * `internal/xworkspaces`: Ignored certain workspace updates (#2275), see #2272 * Logger: Undefined behavior (#2284) * build: * Build issues in older clang versions (#2270, #2279, #2280) --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index 7c5ff776..161ce030 100644 --- a/version.txt +++ b/version.txt @@ -1,4 +1,4 @@ # Polybar version information # Update this on every release # This is used to create the version string if a git repo is not available -3.5.0 +3.5.1