Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package btop for openSUSE:Factory checked in at 2021-10-19 23:03:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/btop (Old) and /work/SRC/openSUSE:Factory/.btop.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "btop" Tue Oct 19 23:03:42 2021 rev:3 rq:926326 version:1.0.18 Changes: -------- --- /work/SRC/openSUSE:Factory/btop/btop.changes 2021-10-11 15:32:06.722892564 +0200 +++ /work/SRC/openSUSE:Factory/.btop.new.1890/btop.changes 2021-10-19 23:03:51.965274003 +0200 @@ -1,0 +2,22 @@ +Tue Oct 19 15:40:53 UTC 2021 - Scott Bradnick <scott.bradn...@suse.com> - 1.0.18 + +- Update to upstream release 1.0.18: + * Fixed: Makefile g++ -dumpmachine failure to get platform on some distros +- Update to upstream release 1.0.17: + * Changed: Reverted mutexes back to custom atomic bool based locks + * Added: Static binaries switched to building with musl + more platforms, by @jan-guenter + * Fixed: Improved battery detection, by @jan-guenter + * Added: Displayed battery selectable in options menu + * Fixed: Battery error if non existent battery named is entered + +------------------------------------------------------------------- +Mon Oct 18 17:33:44 UTC 2021 - Scott Bradnick <scott.bradn...@suse.com> + +- Updating to version 1.0.16 ... + +------------------------------------------------------------------- +Wed Oct 13 15:50:02 UTC 2021 - Scott Bradnick <scott.bradn...@suse.com> + +- Updating to version 1.0.15 ... + +------------------------------------------------------------------- Old: ---- v1.0.14.tar.gz New: ---- v1.0.18.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ btop.spec ++++++ --- /var/tmp/diff_new_pack.CzoCg5/_old 2021-10-19 23:03:52.489274241 +0200 +++ /var/tmp/diff_new_pack.CzoCg5/_new 2021-10-19 23:03:52.493274243 +0200 @@ -17,10 +17,11 @@ Name: btop -Version: 1.0.14 +Version: 1.0.18 Release: 0 Summary: Usage and stats for processor, memory, disks, network and processes License: Apache-2.0 +Group: System/Monitoring URL: https://github.com/aristocratos/btop/archive Source: %{url}/v%{version}.tar.gz#/v%{version}.tar.gz BuildRequires: coreutils @@ -34,7 +35,7 @@ BuildRequires: sed %description -Resource monitor that shows usage and stats for processor, memory, disks, network and processes. C++ version and continuation of bashtop and bpytop. +Resource monitor that shows usage and stats for processor, memory, disks, network and processes.C++ version and continuation of bashtop and bpytop. %prep %setup -q ++++++ v1.0.14.tar.gz -> v1.0.18.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/.editorconfig new/btop-1.0.18/.editorconfig --- old/btop-1.0.14/.editorconfig 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/.editorconfig 2021-10-19 17:29:57.000000000 +0200 @@ -1,3 +1,7 @@ [*.{cpp,h,sh,md,cfg,sample}] indent_style = tab indent_size = 4 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/.github/ISSUE_TEMPLATE/bug_report.md new/btop-1.0.18/.github/ISSUE_TEMPLATE/bug_report.md --- old/btop-1.0.14/.github/ISSUE_TEMPLATE/bug_report.md 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/.github/ISSUE_TEMPLATE/bug_report.md 2021-10-19 17:29:57.000000000 +0200 @@ -44,10 +44,12 @@ If btop++ is crashing at start the following steps could be helpful: +(Extra helpful if compiled with `make OPTFLAGS="-O0 -g"`) + 1. run `gdb btop` 2. `r` to run, wait for crash and press enter -3. `bt` to get backtrace +3. `thread apply all bt` to get backtrace for all threads 4. Copy and paste the backtrace here: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/.github/workflows/continuous-build.yml new/btop-1.0.18/.github/workflows/continuous-build.yml --- old/btop-1.0.14/.github/workflows/continuous-build.yml 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/.github/workflows/continuous-build.yml 2021-10-19 17:29:57.000000000 +0200 @@ -1,7 +1,12 @@ name: Continuous Build Linux on: + workflow_dispatch: push: + branches: + - main + tags-ignore: + - '*.*' paths: - 'src/**' - '!src/osx/**' @@ -11,109 +16,94 @@ - '.github/workflows/continuous-build.yml' jobs: - build: + static-build: + continue-on-error: true + strategy: + matrix: + toolchain: + - aarch64-linux-musl + - aarch64_be-linux-musl + - arm-linux-musleabi + - arm-linux-musleabihf + - armeb-linux-musleabi + - armeb-linux-musleabihf + - armel-linux-musleabi + - armel-linux-musleabihf + - armv5l-linux-musleabi + - armv5l-linux-musleabihf + - armv6-linux-musleabi + - armv6-linux-musleabihf + - armv7l-linux-musleabihf + - armv7m-linux-musleabi + - armv7r-linux-musleabihf + - i486-linux-musl + - i686-linux-musl + - m68k-linux-musl + - mips-linux-musl + - mips-linux-musln32sf + - mips-linux-muslsf + - mips64-linux-musl + - mips64-linux-musln32 + - mips64-linux-musln32sf + - mips64el-linux-musl + - mips64el-linux-musln32 + - mips64el-linux-musln32sf + - mipsel-linux-musl + - mipsel-linux-musln32 + - mipsel-linux-musln32sf + - mipsel-linux-muslsf + - or1k-linux-musl + - powerpc-linux-musl + - powerpc-linux-muslsf + - powerpc64-linux-musl + - powerpc64le-linux-musl + - powerpcle-linux-musl + - powerpcle-linux-muslsf + - riscv32-linux-musl + - riscv64-linux-musl + - s390x-linux-musl + - sh2-linux-musl + - sh2-linux-muslfdpic + - sh2eb-linux-musl + - sh2eb-linux-muslfdpic + - sh4-linux-musl + - sh4eb-linux-musl + - x86_64-linux-musl + - x86_64-linux-muslx32 runs-on: ubuntu-latest - container: ubuntu:21.04 + container: muslcc/x86_64:${{ matrix.toolchain }} steps: - - uses: actions/checkout@v2 - name: Install build tools - run: | - apt update && \ - apt install coreutils sed git build-essential gcc-11 g++-11 -y - apt install -y g++-11-aarch64-linux-gnu g++-11-i686-linux-gnu \ - g++-11-arm-linux-gnueabi g++-11-arm-linux-gnueabihf g++-11-riscv64-linux-gnu \ - g++-11-sparc64-linux-gnu - - mkdir -p multiarch_bin + run: apk add --no-cache coreutils git make tar zstd - git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] + - name: Checkout source + uses: actions/checkout@v2 - - name: Compile x86_64 - run: | - make CXX=g++-11 ARCH=x86_64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-x86_64-$GIT_HASH - make distclean + - name: Fix - Stopping at filesystem boundary + run: git init # [fix Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).] - - name: Compile i686 - run: | - make CXX=i686-linux-gnu-g++-11 ARCH=i686 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-i686-$GIT_HASH - make distclean + - name: Build + run: make STATIC=true STRIP=true QUIET=true - - name: Compile aarch64 - run: | - make CXX=aarch64-linux-gnu-g++-11 ARCH=aarch64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-aarch64-$GIT_HASH - make distclean - - - name: Compile armel - run: | - make CXX=arm-linux-gnueabi-g++-11 ARCH=armel STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armel-$GIT_HASH - make distclean - - - name: Compile armhf - run: | - make CXX=arm-linux-gnueabihf-g++-11 ARCH=armhf STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-armhf-$GIT_HASH - make distclean - - - name: Compile riscv64 - run: | - make CXX=riscv64-linux-gnu-g++-11 ARCH=riscv64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-riscv64-$GIT_HASH - make distclean + - name: Make executable + run: chmod +x bin/* - - name: Compile sparc64 + - name: Set up directories run: | - make CXX=sparc64-linux-gnu-g++-11 ARCH=sparc64 STATIC=true QUIET=true - GIT_HASH=$(git rev-parse --short "$GITHUB_SHA") - mv bin/btop multiarch_bin/btop-sparc64-$GIT_HASH - make distclean + mkdir .artifacts + mkdir .package - - name: Make executable + - name: Create binary atrifacts run: | - chmod +x multiarch_bin/* - - - uses: actions/upload-artifact@v2 - with: - name: btop-x86_64 - path: 'multiarch_bin/btop-x86_64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-i686 - path: 'multiarch_bin/btop-i686*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-aarch64 - path: 'multiarch_bin/btop-aarch64*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armel - path: 'multiarch_bin/btop-armel*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-armhf - path: 'multiarch_bin/btop-armhf*' - - - uses: actions/upload-artifact@v2 - with: - name: btop-riscv64 - path: 'multiarch_bin/btop-riscv64*' + TOOLCHAIN=${{ matrix.toolchain }} + GIT_HASH=$(git rev-parse --short "${{ github.sha }}") + FILENAME=btop-${TOOLCHAIN/linux-musl/}-$GIT_HASH + cp bin/btop .artifacts/$FILENAME - - uses: actions/upload-artifact@v2 + - name: Upload artifacts + uses: actions/upload-artifact@v2 with: - name: btop-sparc64 - path: 'multiarch_bin/btop-sparc64*' + name: btop-${{ matrix.toolchain }} + path: '.artifacts/**' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/CHANGELOG.md new/btop-1.0.18/CHANGELOG.md --- old/btop-1.0.14/CHANGELOG.md 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/CHANGELOG.md 2021-10-19 17:29:57.000000000 +0200 @@ -1,3 +1,45 @@ +## v1.0.18 + +* Fixed: Makefile g++ -dumpmachine failure to get platform on some distros + +## v1.0.17 + +* Changed: Reverted mutexes back to custom atomic bool based locks + +* Added: Static binaries switched to building with musl + more platforms, by @jan-guenter + +* Fixed: Improved battery detection, by @jan-guenter + +* Added: Displayed battery selectable in options menu + +* Fixed: Battery error if non existent battery named is entered + +## v1.0.16 + +* Fixed: atomic_wait() and atomic_lock{} use cpu pause instructions instead of thread sleep + +* Fixed: Swapped from atomic bool spinlocks to mutexes to fix rare deadlock + +* Added: Continuous Build workflow for OSX branch, by @ShrirajHegde + +* Changed: Reverted thread mutex lock to atomic bool with wait and timeout + +* Changed: Removed unnecessary async threads in Runner thread + +* Added: Try to restart secondary thread in case of stall and additional error checks for ifstream in Proc::collect() + +* Fixed: change [k]ill to [K]ill when enabling vim keys, by @jlopezcur + +## v1.0.15 + +* Fixed: Extra "root" partition when running in snap + +* Changed: Limit atomic_wait() to 1000ms to fix rare stall + +* Fixed: Removed unneeded lock in Runner::run() + +* Added: Toggle in options for enabling directional vim keys "h,j,k,l" + ## v1.0.14 * Changed: Total system memory is checked at every update instead of once at start Binary files old/btop-1.0.14/Img/logo.png and new/btop-1.0.18/Img/logo.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/Img/logo.svg new/btop-1.0.18/Img/logo.svg --- old/btop-1.0.14/Img/logo.svg 1970-01-01 01:00:00.000000000 +0100 +++ new/btop-1.0.18/Img/logo.svg 2021-10-19 17:29:57.000000000 +0200 @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="341" height="90" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <defs> + <pattern id="red-stripes" width="341" height="90" patternUnits="userSpaceOnUse"> + <rect width="341" height="16" fill="#f00"/> + <rect y="16" width="341" height="16" fill="#d70000"/> + <rect y="32" width="341" height="16" fill="#af0000"/> + <rect y="48" width="341" height="16" fill="#870000"/> + <rect y="64" width="341" height="16" fill="#5f0000"/> + </pattern> + <pattern id="gray-stripes" width="341" height="90" patternUnits="userSpaceOnUse"> + <rect width="341" height="16" fill="#585858"/> + <rect y="16" width="341" height="16" fill="#4e4e4e"/> + <rect y="32" width="341" height="16" fill="#444"/> + <rect y="48" width="341" height="16" fill="#3a3a3a"/> + <rect y="64" width="341" height="16" fill="#303030"/> + <rect y="80" width="341" height="10" fill="#262626"/> + </pattern> + </defs> + <g fill="#080808"> + <path d="m2,7v83h45v-16h7v-19h-7v-13h7v-19h-7v-16h-45zm17,19h18v13h-18v-13zm0,32h18v13h-18v-13z"/> + <path d="m58,7v19h21v64h17v-64h21v-19h-59z"/> + <path d="m128,7v16h-7v51h7v16h45v-16h7v-51h-7v-16h-45zm10,19h25v45h-25v-45z"/> + <path d="m184,7v83h17v-32h28v-16h7v-19h-7v-16h-45zm17,19h18v13h-18v-13z"/> + <path d="m261,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17z"/> + <path d="m310,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17z"/> + </g> + <g fill="url(#gray-stripes)"> + <path d="m2,7v83h45v-16h7v-19h-7v-13h7v-19h-7v-16h-45zm1,1h43v16h7v17h-7v15h7v17h-7v16h-43v-81zm15,17h20v15h-20v-15zm1,1v13h18v-13h-18zm-1,31h20v15h-20v-15zm1,1v13h18v-13h-18zm-15-49v79h41v-16h7v-15h-7v-17h7v-15h-7v-16h-41zm1,1h39v16h7v13h-7v19h7v13h-7v16h-39v-77zm11,13h24v19h-24v-19zm1,1v17h22v-17h-22zm-1,31h24v19h-24v-19zm1,1v17h22v-17h-22z"/> + <path d="m58,7v19h21v64h17v-64h21v-19h-59zm1,1h57v17h-21v64h-15v-64h-21v-17zm1,1v15h21v64h13v-64h21v-15h-55zm1,1h53v13h-21v64h-11v-64h-21v-13z"/> + <path d="m128,7v16h-7v51h7v16h45v-16h7v-51h-7v-16h-45zm1,1h43v16h7v49h-7v16h-43v-16h-7v-49h7v-16zm9,18v45h25v-45h-25zm-1-1h27v47h-27v-47zm-7-16v16h-7v47h7v16h41v-16h7v-47h-7v-16h-41zm1,1h39v16h7v45h-7v16h-39v-16h-7v-45h7v-16zm5,14v49h29v-49h-29zm-1-1h31v51h-31v-51z"/> + <path d="m184,7v83h17v-32h28v-16h7v-19h-7v-16h-45zm1,1h43v16h7v17h-7v16h-28v32h-15v-81zm16,18v13h18v-13h-18zm-1-1h20v15h-20v-15zm-14-16v79h13v-32h28v-16h7v-15h-7v-16h-41zm1,1h39v16h7v13h-7v16h-28v32h-11v-77zm12,14v17h22v-17h-22zm-1-1h24v19h-24v-19z"/> + <path d="m261,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17zm1,1h15v16h14v17h-14v16h-15v-16h-14v-17h14v-16zm1,1v16h-14v15h14v16h13v-16h14v-15h-14v-16h-13zm1,1h11v16h14v13h-14v16h-11v-16h-14v-13h14v-16z"/> + <path d="m310,23v16h-14v19h14v16h17v-16h14v-19h-14v-16h-17zm1,1h15v16h14v17h-14v16h-15v-16h-14v-17h14v-16zm1,1v16h-14v15h14v16h13v-16h14v-15h-14v-16h-13zm1,1h11v16h14v13h-14v16h-11v-16h-14v-13h14v-16z"/> + </g> + <g fill="url(#red-stripes)"> + <path d="m0,0v80h42v-16h7v-16h-7v-16h7v-16h-7v-16h-42zm14,16h21v16h-21v-16zm0,32h21v16h-21v-16z"/> + <path d="m56,0v16h21v64h14v-64h21v-16h-56z"/> + <path d="m126,0v16h-7v48h7v16h42v-16h7v-48h-7v-16h-42zm7,16h28v48h-28v-48z"/> + <path d="m182,0v80h14v-32h28v-16h7v-16h-7v-16h-42zm14,16h21v16h-21v-16z"/> + <path d="m259,16v16h-14v16h14v16h14v-16h14v-16h-14v-16h-14z"/> + <path d="m308,16v16h-14v16h14v16h14v-16h14v-16h-14v-16h-14z"/> + </g> +</svg> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/Makefile new/btop-1.0.18/Makefile --- old/btop-1.0.14/Makefile 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/Makefile 2021-10-19 17:29:57.000000000 +0200 @@ -1,6 +1,6 @@ #* Btop++ makefile v1.2 -BANNER = \n \033[38;5;196m??????????????????\033[38;5;240m??? \033[38;5;196m????????????????????????\033[38;5;240m??? \033[38;5;196m??????????????????\033[38;5;240m??? \033[38;5;196m??????????????????\033[38;5;240m???\n \033[38;5;160m??????\033[38;5;239m?????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m???\033[38;5;160m??????\033[38;5;239m?????????\033[38;5;160m??????\033[38;5;239m??? \033[38;5;160m??????\033[38;5;239m??? \033[38;5;160m??????\033[38;5;239m???\n \033[38;5;124m??????????????????\033[38;5;238m?????? \033[38;5;124m??????\033[38;5;238m??? \033[38;5;124m??????\033[38;5;238m??? \033[38;5;124m??????\033[38;5;238m???\033[38;5;124m??????????????????\033[38;5;238m?????? \033[38;5;124m??????????????????\033[38;5;238m???\033[38;5;124m??????????????????\033[38;5;238m???\n \033[38;5;88m??????\033[38;5;237m?????????\033[38;5;88m??????\033[38 ;5;237m??? \033[38;5;88m??????\033[38;5;237m??? \033[38;5;88m??????\033[38;5;237m??? \033[38;5;88m??????\033[38;5;237m???\033[38;5;88m??????\033[38;5;237m??????????????? ??????\033[38;5;88m??????\033[38;5;237m???????????????\033[38;5;88m??????\033[38;5;237m?????????\n \033[38;5;52m??????????????????\033[38;5;236m?????? \033[38;5;52m??????\033[38;5;236m??? ???\033[38;5;52m??????????????????\033[38;5;236m??????\033[38;5;52m??????\033[38;5;236m??? ????????? ?????????\n \033[38;5;235m????????????????????? ????????? ????????????????????? ????????? \033[1;3;38;5;240mMakefile v1.2\033[0m +BANNER = \n \033[38;5;196m??????????????????\033[38;5;240m??? \033[38;5;196m????????????????????????\033[38;5;240m??? \033[38;5;196m??????????????????\033[38;5;240m??? \033[38;5;196m??????????????????\033[38;5;240m???\n \033[38;5;160m??????\033[38;5;239m?????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m????????????\033[38;5;160m??????\033[38;5;239m???\033[38;5;160m??????\033[38;5;239m?????????\033[38;5;160m??????\033[38;5;239m??? \033[38;5;160m??????\033[38;5;239m??? \033[38;5;160m??????\033[38;5;239m???\n \033[38;5;124m??????????????????\033[38;5;238m?????? \033[38;5;124m??????\033[38;5;238m??? \033[38;5;124m??????\033[38;5;238m??? \033[38;5;124m??????\033[38;5;238m???\033[38;5;124m??????????????????\033[38;5;238m?????? \033[38;5;124m??????????????????\033[38;5;238m???\033[38;5;124m??????????????????\033[38;5;238m???\n \033[38;5;88m??????\033[38;5;237m?????????\033[38;5;88m??????\033[38 ;5;237m??? \033[38;5;88m??????\033[38;5;237m??? \033[38;5;88m??????\033[38;5;237m??? \033[38;5;88m??????\033[38;5;237m???\033[38;5;88m??????\033[38;5;237m??????????????? ??????\033[38;5;88m??????\033[38;5;237m???????????????\033[38;5;88m??????\033[38;5;237m?????????\n \033[38;5;52m??????????????????\033[38;5;236m?????? \033[38;5;52m??????\033[38;5;236m??? ???\033[38;5;52m??????????????????\033[38;5;236m??????\033[38;5;52m??????\033[38;5;236m??? ????????? ?????????\n \033[38;5;235m????????????????????? ????????? ????????????????????? ????????? \033[1;3;38;5;240mMakefile v1.3\033[0m override BTOP_VERSION := $(shell head -n100 src/btop.cpp 2>/dev/null | grep "Version =" | cut -f2 -d"\"" || echo " unknown") override TIMESTAMP := $(shell date +%s 2>/dev/null || echo "0") @@ -14,24 +14,26 @@ PREFIX ?= /usr/local -#? NOTICE! Manually set PLATFORM and ARCH if not compiling for host system +#? Detect PLATFORM and ARCH from uname/gcc if not set PLATFORM ?= $(shell uname -s || echo unknown) -ARCH ?= $(shell uname -m || echo unknown) +ifneq ($(filter unknown darwin, $(PLATFORM)),) + override PLATFORM := $(shell $(CXX) -dumpmachine | awk -F"-" '{ print (NF==4) ? $$3 : $$2 }') +endif +ARCH ?= $(shell $(CXX) -dumpmachine | cut -d "-" -f 1) + +override PLATFORM_LC := $(shell echo $(PLATFORM) | tr '[:upper:]' '[:lower:]') #? Only enable fcf-protection if on x86_64 -ifeq ($(ARCH),x86_64) +ifneq ($(filter x86_64 i%86, $(ARCH)),) override ADDFLAGS += -fcf-protection endif ifeq ($(STATIC),true) - override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ + override ADDFLAGS += -D STATIC_BUILD -static -static-libgcc -static-libstdc++ -Wl,--fatal-warnings endif -#? Make sure PLATFORM Darwin is OSX and not Darwin -ifeq ($(PLATFORM),Darwin) - ifeq ($(shell sw_vers >/dev/null 2>&1; echo $$?),0) - PLATFORM := OSX - endif +ifeq ($(STRIP),true) + override ADDFLAGS += -s endif #? Compiler and Linker @@ -50,13 +52,13 @@ endif #? Pull in platform specific source files and get thread count -ifeq ($(PLATFORM),Linux) +ifeq ($(PLATFORM_LC),linux) PLATFORM_DIR := linux THREADS := $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),FreeBSD) +else ifeq ($(PLATFORM_LC),freebsd) PLATFORM_DIR := freebsd THREADS := $(shell getconf NPROCESSORS_ONLN 2>/dev/null || echo 1) -else ifeq ($(PLATFORM),OSX) +else ifeq ($(PLATFORM_LC),apple) PLATFORM_DIR := osx THREADS := $(shell sysctl -n hw.ncpu || echo 1) else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/README.md new/btop-1.0.18/README.md --- old/btop-1.0.14/README.md 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/README.md 2021-10-19 17:29:57.000000000 +0200 @@ -38,6 +38,11 @@ ### Under development +##### 6 October 2021 + +OsX development have been started by @joske , big thanks :) +See branch [OSX](https://github.com/aristocratos/btop/tree/OSX) for current progress. + ##### 18 September 2021 The Linux version of btop++ is complete. Released as version 1.0.0 @@ -170,7 +175,7 @@ ## Installation -**Binary release (statically compiled, for kernel 3.2.0 and newer)** +**Binary release (statically compiled with musl, for kernel 2.6.39 and newer)** 1. **Download btop-(VERSION)-(PLATFORM)-(ARCH).tbz from [latest release](https://github.com/aristocratos/btop/releases/latest) and unpack to a new folder** @@ -232,11 +237,14 @@ The makefile also needs GNU coreutils and `sed` (should already be installed on any modern distribution). + For a `cmake` based build alternative see the [fork](https://github.com/jan-guenter/btop/tree/main) by @jan-guenter + 1. **Install dependencies (example for Ubuntu 21.04 Hirsute)** + Use gcc-10 g++-10 if gcc-11 isn't available + ``` bash sudo apt install coreutils sed git build-essential gcc-11 g++-11 - # use gcc-10 g++-10 if gcc-11 isn't available ``` 2. **Clone repository** @@ -250,15 +258,20 @@ Append `STATIC=true` to `make` command for static compilation. - Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users when compiling statically. + Notice! If using LDAP Authentication, usernames will show as UID number for LDAP users if compiling statically with glibc. Append `QUIET=true` for less verbose output. - Notice! Manually set `$ARCH` variable if cross-compiling + Append `STRIP=true` to force stripping of debug symbols (adds `-s` linker flag). + + Append `ARCH=<architecture>` to manually set the target architecture. + If omitted the makefile uses the machine triple (output of `-dumpmachine` compiler parameter) to detect the target system. Use `ADDFLAGS` variable for appending flags to both compiler and linker. - For example: `make ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + For example: `ADDFLAGS=-march=native` might give a performance boost if compiling only for your own system. + + If `g++` is linked to an older version of gcc on your system specify the correct version by appending `CXX=g++-10` or `CXX=g++-11`. ``` bash make @@ -266,9 +279,11 @@ 4. **Install** + Append `PREFIX=/target/dir` to set target, default: `/usr/local` + + Notice! Only use "sudo" when installing to a NON user owned directory. + ``` bash - # use "make install PREFIX=/target/dir" to set target, default: /usr/local - # only use "sudo" when installing to a NON user owned directory sudo make install ``` @@ -276,9 +291,11 @@ No need for `sudo` to enable signal sending to any process and to prevent /proc read permissions problems on some systems. + Run after make install and use same PREFIX if any was used at install. + + Set `SU_USER` and `SU_GROUP` to select user and group, default is `root` and `root` + ``` bash - # run after make install and use same PREFIX if any was used at install - # set SU_USER and SU_GROUP to select user and group, default is root:root sudo make setuid ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop.cpp new/btop-1.0.18/src/btop.cpp --- old/btop-1.0.14/src/btop.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -19,8 +19,6 @@ #include <csignal> #include <pthread.h> #include <thread> -#include <future> -#include <bitset> #include <numeric> #include <ranges> #include <unistd.h> @@ -40,7 +38,7 @@ #include <btop_menu.hpp> using std::string, std::string_view, std::vector, std::atomic, std::endl, std::cout, std::min, std::flush, std::endl; -using std::string_literals::operator""s, std::to_string, std::future, std::async, std::bitset, std::future_status; +using std::string_literals::operator""s, std::to_string; namespace fs = std::filesystem; namespace rng = std::ranges; using namespace Tools; @@ -55,7 +53,7 @@ {"#801414", "???????????????????????? ????????? ???????????????????????????????????? ????????? ?????????"}, {"#000000", "????????????????????? ????????? ????????????????????? ?????????"}, }; - const string Version = "1.0.14"; + const string Version = "1.0.18"; int coreCount; string overlay; @@ -79,7 +77,6 @@ uint64_t start_time; atomic<bool> resized (false); - atomic<bool> resizing (false); atomic<bool> quitting (false); atomic<bool> _runner_started (false); @@ -150,8 +147,8 @@ //* Handler for SIGWINCH and general resizing events, does nothing if terminal hasn't been resized unless force=true void term_resize(bool force) { - if (Global::resizing) return; - atomic_lock lck(Global::resizing); + static atomic<bool> resizing (false); + atomic_lock lck(resizing, true); if (auto refreshed = Term::refresh(true); refreshed or force) { if (force and refreshed) force = false; } @@ -200,8 +197,13 @@ if (Global::quitting) return; Global::quitting = true; Runner::stop(); - if (Global::_runner_started and pthread_join(Runner::runner_id, NULL) != 0) { - Logger::error("Failed to join _runner thread!"); + if (Global::_runner_started) { + struct timespec ts; + ts.tv_sec = 5; + if (pthread_timedjoin_np(Runner::runner_id, NULL, &ts) != 0) { + Logger::error("Failed to join _runner thread!"); + pthread_cancel(Runner::runner_id); + } } Config::write(); @@ -303,20 +305,6 @@ pthread_t runner_id; pthread_mutex_t mtx; - const unordered_flat_map<string, uint_fast8_t> box_bits = { - {"proc", 0b0000'0001}, - {"net", 0b0000'0100}, - {"mem", 0b0001'0000}, - {"cpu", 0b0100'0000}, - }; - - enum bit_pos { - proc_present, proc_running, - net_present, net_running, - mem_present, mem_running, - cpu_present, cpu_running - }; - enum debug_actions { collect_begin, draw_begin, @@ -328,16 +316,11 @@ draw }; - const uint_fast8_t proc_done = 0b0000'0011; - const uint_fast8_t net_done = 0b0000'1100; - const uint_fast8_t mem_done = 0b0011'0000; - const uint_fast8_t cpu_done = 0b1100'0000; - string debug_bg; unordered_flat_map<string, array<uint64_t, 2>> debug_times; struct runner_conf { - bitset<8> box_mask; + vector<string> boxes; bool no_update; bool force_redraw; bool background_update; @@ -387,7 +370,15 @@ //* ----------------------------------------------- THREAD LOOP ----------------------------------------------- while (not Global::quitting) { thread_wait(); + atomic_wait_for(active, true, 5000); + if (active) { + Global::exit_error_msg = "Runner thread failed to get active lock!"; + Global::thread_exception = true; + Input::interrupt = true; + stopping = true; + } if (stopping or Global::resized) { + sleep_ms(1); continue; } @@ -405,128 +396,86 @@ output.clear(); - //* Start collection functions for all boxes in async threads and draw in this thread when finished - //? Starting order below based on mean time to finish + //* Run collection and draw functions for all boxes try { - future<Cpu::cpu_info&> cpu; - future<Mem::mem_info&> mem; - future<Net::net_info&> net; - future<vector<Proc::proc_info>&> proc; - - //? Loop until all box flags present in bitmask have been zeroed - while (conf.box_mask.count() > 0) { - if (stopping) break; - - //? PROC - if (conf.box_mask.test(proc_present)) { - if (not conf.box_mask.test(proc_running)) { - if (Global::debug) debug_timer("proc", collect_begin); - - //? Start async collect - proc = async(Proc::collect, conf.no_update); - conf.box_mask.set(proc_running); - } - else if (not proc.valid()) - throw std::runtime_error("Proc::collect() future not valid."); + //? PROC + if (v_contains(conf.boxes, "proc")) { + try { + if (Global::debug) debug_timer("proc", collect_begin); - else if (proc.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("proc", draw_begin); + //? Start collect + auto proc = Proc::collect(conf.no_update); - //? Draw box - if (not pause_output) output += Proc::draw(proc.get(), conf.force_redraw, conf.no_update); + if (Global::debug) debug_timer("proc", draw_begin); - if (Global::debug) debug_timer("proc", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Proc:: -> " + (string)e.what()); - } - conf.box_mask ^= proc_done; - } + //? Draw box + if (not pause_output) output += Proc::draw(proc, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("proc", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Proc:: -> " + (string)e.what()); } + } - //? NET - if (conf.box_mask.test(net_present)) { - if (not conf.box_mask.test(net_running)) { - if (Global::debug) debug_timer("net", collect_begin); - - //? Start async collect - net = async(Net::collect, conf.no_update); - conf.box_mask.set(net_running); - } - else if (not net.valid()) - throw std::runtime_error("Net::collect() future not valid."); - else if (net.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("net", draw_begin); + //? NET + if (v_contains(conf.boxes, "net")) { + try { + if (Global::debug) debug_timer("net", collect_begin); - //? Draw box - if (not pause_output) output += Net::draw(net.get(), conf.force_redraw, conf.no_update); + //? Start collect + auto net = Net::collect(conf.no_update); - if (Global::debug) debug_timer("net", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Net:: -> " + (string)e.what()); - } - conf.box_mask ^= net_done; - } + if (Global::debug) debug_timer("net", draw_begin); + + //? Draw box + if (not pause_output) output += Net::draw(net, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("net", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Net:: -> " + (string)e.what()); } + } - //? MEM - if (conf.box_mask.test(mem_present)) { - if (not conf.box_mask.test(mem_running)) { - if (Global::debug) debug_timer("mem", collect_begin); - - //? Start async collect - mem = async(Mem::collect, conf.no_update); - conf.box_mask.set(mem_running); - } - else if (not mem.valid()) - throw std::runtime_error("Mem::collect() future not valid."); + //? MEM + if (v_contains(conf.boxes, "mem")) { + try { + if (Global::debug) debug_timer("mem", collect_begin); - else if (mem.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("mem", draw_begin); + //? Start collect + auto mem = Mem::collect(conf.no_update); - //? Draw box - if (not pause_output) output += Mem::draw(mem.get(), conf.force_redraw, conf.no_update); + if (Global::debug) debug_timer("mem", draw_begin); - if (Global::debug) debug_timer("mem", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Mem:: -> " + (string)e.what()); - } - conf.box_mask ^= mem_done; - } + //? Draw box + if (not pause_output) output += Mem::draw(mem, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("mem", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Mem:: -> " + (string)e.what()); } + } - //? CPU - if (conf.box_mask.test(cpu_present)) { - if (not conf.box_mask.test(cpu_running)) { - if (Global::debug) debug_timer("cpu", collect_begin); - - //? Start async collect - cpu = async(Cpu::collect, conf.no_update); - conf.box_mask.set(cpu_running); - } - else if (not cpu.valid()) - throw std::runtime_error("Cpu::collect() future not valid."); + //? CPU + if (v_contains(conf.boxes, "cpu")) { + try { + if (Global::debug) debug_timer("cpu", collect_begin); - else if (cpu.wait_for(10us) == future_status::ready) { - try { - if (Global::debug) debug_timer("cpu", draw_begin); + //? Start collect + auto cpu = Cpu::collect(conf.no_update); - //? Draw box - if (not pause_output) output += Cpu::draw(cpu.get(), conf.force_redraw, conf.no_update); + if (Global::debug) debug_timer("cpu", draw_begin); - if (Global::debug) debug_timer("cpu", draw_done); - } - catch (const std::exception& e) { - throw std::runtime_error("Cpu:: -> " + (string)e.what()); - } - conf.box_mask ^= cpu_done; - } + //? Draw box + if (not pause_output) output += Cpu::draw(cpu, conf.force_redraw, conf.no_update); + + if (Global::debug) debug_timer("cpu", draw_done); + } + catch (const std::exception& e) { + throw std::runtime_error("Cpu:: -> " + (string)e.what()); } } } @@ -589,8 +538,17 @@ //* Runs collect and draw in a secondary thread, unlocks and locks config to update cached values void run(const string& box, const bool no_update, const bool force_redraw) { - atomic_lock lck(waiting); - atomic_wait(active); + atomic_wait_for(active, true, 5000); + if (active) { + Logger::error("Stall in Runner thread, restarting!"); + active = false; + // exit(1); + pthread_cancel(Runner::runner_id); + if (pthread_create(&Runner::runner_id, NULL, &Runner::_runner, NULL) != 0) { + Global::exit_error_msg = "Failed to re-create _runner thread!"; + exit(1); + } + } if (stopping or Global::resized) return; if (box == "overlay") { @@ -603,21 +561,21 @@ Config::unlock(); Config::lock(); - //? Setup bitmask for selected boxes and pass to _runner thread - bitset<8> box_mask; - for (const auto& box : (box == "all" ? Config::current_boxes : vector{box})) { - box_mask |= box_bits.at(box); - } - - current_conf = {box_mask, no_update, force_redraw, (not Config::getB("tty_mode") and Config::getB("background_update")), Global::overlay, Global::clock}; + current_conf = { + (box == "all" ? Config::current_boxes : vector{box}), + no_update, force_redraw, + (not Config::getB("tty_mode") and Config::getB("background_update")), + Global::overlay, + Global::clock + }; if (Menu::active and not current_conf.background_update) Global::overlay.clear(); thread_trigger(); - - //? Wait for _runner thread to be active before returning - for (int i = 0; not active and i < 10; i++) sleep_ms(1); + atomic_wait_for(active, false, 10); } + + } //* Stops any work being done in runner thread and checks for thread errors @@ -630,9 +588,20 @@ exit(1); } else if (ret == EBUSY) { - atomic_wait(active); + atomic_wait_for(active, true, 5000); + if (active) { + active = false; + if (Global::quitting) { + return; + } + else { + Global::exit_error_msg = "No response from Runner thread, quitting!"; + exit(1); + } + } thread_trigger(); - sleep_ms(1); + atomic_wait_for(active, false, 100); + atomic_wait_for(active, true, 100); } stopping = false; } @@ -858,7 +827,7 @@ Global::resized = false; if (Menu::active) Menu::process(); else Runner::run("all", true, true); - atomic_wait(Runner::active); + atomic_wait_for(Runner::active, true, 1000); } //? Update clock if needed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_config.cpp new/btop-1.0.18/src/btop_config.cpp --- old/btop-1.0.14/src/btop_config.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_config.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -54,6 +54,9 @@ "#* Use withespace \" \" as seprator between different presets.\n" "#* Example: \"cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty\""}, + {"vim_keys", "#* Set to True to enable \"h,j,k,l\" keys for directional control in lists.\n" + "#* Conflicting keys for h:\"help\" and k:\"kill\" is accessible while holding shift."}, + {"rounded_corners", "#* Rounded corners on boxes, is ignored if TTY mode is ON."}, {"graph_symbol", "#* Default symbols to use for graph creation, \"braille\", \"block\" or \"tty\".\n" @@ -167,6 +170,8 @@ {"show_battery", "#* Show battery stats in top right if battery is present."}, + {"selected_battery", "#* Which battery to use if multiple are present. \"Auto\" for auto detection."}, + {"log_level", "#* Set loglevel for \"~/.config/btop/btop.log\" levels are: \"ERROR\" \"WARNING\" \"INFO\" \"DEBUG\".\n" "#* The level set includes all lower levels, i.e. \"DEBUG\" will show all logging info."} }; @@ -184,6 +189,7 @@ {"cpu_graph_upper", "total"}, {"cpu_graph_lower", "total"}, {"cpu_sensor", "Auto"}, + {"selected_battery", "Auto"}, {"cpu_core_map", ""}, {"temp_scale", "celsius"}, {"clock_format", "%X"}, @@ -231,6 +237,7 @@ {"net_auto", true}, {"net_sync", false}, {"show_battery", true}, + {"vim_keys", false}, {"tty_mode", false}, {"force_tty", false}, {"lowcolor", false}, @@ -252,7 +259,7 @@ unordered_flat_map<string, int> intsTmp; bool _locked(const string& name) { - atomic_wait(writelock); + atomic_wait(writelock, true); if (not write_new and rng::find_if(descriptions, [&name](const auto& a) { return a.at(0) == name; }) != descriptions.end()) write_new = true; return locked.load(); @@ -261,6 +268,8 @@ fs::path conf_dir; fs::path conf_file; + vector<string> available_batteries = {"Auto"}; + vector<string> current_boxes; vector<string> preset_list = {"cpu:0:default,mem:0:default,net:0:default,proc:0:default"}; int current_preset = -1; @@ -444,7 +453,7 @@ void unlock() { if (not locked) return; atomic_wait(Runner::active); - atomic_lock lck(writelock); + atomic_lock lck(writelock, true); try { if (Proc::shown) { ints.at("selected_pid") = Proc::selected_pid; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_config.hpp new/btop-1.0.18/src/btop_config.hpp --- old/btop-1.0.14/src/btop_config.hpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_config.hpp 2021-10-19 17:29:57.000000000 +0200 @@ -45,6 +45,7 @@ extern vector<string> current_boxes; extern vector<string> preset_list; + extern vector<string> available_batteries; extern int current_preset; //* Check if string only contains space seperated valid names for boxes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_draw.cpp new/btop-1.0.18/src/btop_draw.cpp --- old/btop-1.0.14/src/btop_draw.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_draw.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -1039,9 +1039,10 @@ auto selected = Config::getI("proc_selected"); auto last_selected = Config::getI("proc_last_selected"); const int select_max = (Config::getB("show_detailed") ? Proc::select_max - 8 : Proc::select_max); + auto& vim_keys = Config::getB("vim_keys"); int numpids = Proc::numpids; - if (cmd_key == "up" and selected > 0) { + if ((cmd_key == "up" or (vim_keys and cmd_key == "k")) and selected > 0) { if (start > 0 and selected == 1) start--; else selected--; if (Config::getI("proc_last_selected") > 0) Config::set("proc_last_selected", 0); @@ -1052,7 +1053,7 @@ else if (cmd_key == "mouse_scroll_down" and start < numpids - select_max) { start = min(numpids - select_max, start + 3); } - else if (cmd_key == "down") { + else if (cmd_key == "down" or (vim_keys and cmd_key == "j")) { if (start < numpids - select_max and selected == select_max) start++; else if (selected == 0 and last_selected > 0) { selected = last_selected; @@ -1103,6 +1104,7 @@ auto& graph_symbol = (tty_mode ? "tty" : Config::getS("graph_symbol_proc")); auto& graph_bg = Symbols::graph_symbols.at((graph_symbol == "default" ? Config::getS("graph_symbol") + "_up" : graph_symbol + "_up")).at(6); auto& mem_bytes = Config::getB("proc_mem_bytes"); + auto& vim_keys = Config::getB("vim_keys"); start = Config::getI("proc_start"); selected = Config::getI("proc_selected"); const int y = show_detailed ? Proc::y + 8 : Proc::y; @@ -1167,7 +1169,7 @@ if (alive and selected == 0) Input::mouse_mappings["t"] = {d_y, mouse_x, 1, 9}; mouse_x += 11; } - out += title_left + hi_color + Fx::b + 'k' + t_color + "ill" + Fx::ub + title_right + out += title_left + hi_color + Fx::b + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right + title_left + hi_color + Fx::b + 's' + t_color + "ignals" + Fx::ub + title_right + Mv::to(d_y, d_x + d_width - 10) + title_left + t_color + Fx::b + hide + Symbols::enter + Fx::ub + title_right; if (alive and selected == 0) { @@ -1260,7 +1262,7 @@ mouse_x += 11; } if (width > 55) { - out += title_left_down + Fx::b + hi_color + 'k' + t_color + "ill" + Fx::ub + title_right_down; + out += title_left_down + Fx::b + hi_color + (vim_keys ? 'K' : 'k') + t_color + "ill" + Fx::ub + title_right_down; if (selected > 0) Input::mouse_mappings["k"] = {y + height - 1, mouse_x, 1, 4}; mouse_x += 6; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_input.cpp new/btop-1.0.18/src/btop_input.cpp --- old/btop-1.0.14/src/btop_input.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_input.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -182,7 +182,9 @@ if (key.empty()) return; try { auto& filtering = Config::getB("proc_filtering"); - + auto& vim_keys = Config::getB("vim_keys"); + auto help_key = (vim_keys ? "H" : "h"); + auto kill_key = (vim_keys ? "K" : "k"); //? Global input actions if (not filtering) { bool keep_going = false; @@ -193,7 +195,7 @@ Menu::show(Menu::Menus::Main); return; } - else if (is_in(key, "F1", "h")) { + else if (is_in(key, "F1", help_key)) { Menu::show(Menu::Menus::Help); return; } @@ -252,13 +254,13 @@ else return; } - else if (key == "left") { + else if (key == "left" or (vim_keys and key == "h")) { int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting")); if (--cur_i < 0) cur_i = Proc::sort_vector.size() - 1; Config::set("proc_sorting", Proc::sort_vector.at(cur_i)); } - else if (key == "right") { + else if (key == "right" or (vim_keys and key == "l")) { int cur_i = v_index(Proc::sort_vector, Config::getS("proc_sorting")); if (std::cmp_greater(++cur_i, Proc::sort_vector.size() - 1)) cur_i = 0; @@ -344,7 +346,7 @@ if (key == "-" or key == "space") Proc::collapse = pid; no_update = false; } - else if (is_in(key, "t", "k") and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) { + else if (is_in(key, "t", kill_key) and (Config::getB("show_detailed") or Config::getI("selected_pid") > 0)) { atomic_wait(Runner::active); if (Config::getB("show_detailed") and Config::getI("proc_selected") == 0 and Proc::detailed.status == "Dead") return; Menu::show(Menu::Menus::SignalSend, (key == "t" ? SIGTERM : SIGKILL)); @@ -356,7 +358,7 @@ Menu::show(Menu::Menus::SignalChoose); return; } - else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end")) { + else if (is_in(key, "up", "down", "page_up", "page_down", "home", "end") or (vim_keys and is_in(key, "j", "k"))) { proc_mouse_scroll: redraw = false; auto old_selected = Config::getI("proc_selected"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_menu.cpp new/btop-1.0.18/src/btop_menu.cpp --- old/btop-1.0.14/src/btop_menu.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_menu.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -177,6 +177,15 @@ "Will force 16-color mode and TTY theme,", "set all graph symbols to \"tty\" and swap", "out other non tty friendly symbols."}, + {"vim_keys", + "Enable vim keys.", + "Set to True to enable \"h,j,k,l\" keys for", + "directional control in lists.", + "", + "Conflicting keys for", + "h (help) and k (kill)", + "is accessible while holding shift."}, + {"presets", "Define presets for the layout of the boxes.", "", @@ -261,6 +270,13 @@ "", "Show battery stats in the top right corner", "if a battery is present."}, + {"selected_battery", + "Select battery.", + "", + "Which battery to use if multiple are present.", + "Can be both batteries and UPS.", + "", + "\"Auto\" for auto detection."}, {"log_level", "Set loglevel for error.log", "", @@ -695,7 +711,7 @@ else if (key == "backspace" and selected_signal != -1) { selected_signal = (selected_signal < 10 ? -1 : selected_signal / 10); } - else if (key == "up" and selected_signal != 16) { + else if (is_in(key, "up", "k") and selected_signal != 16) { if (selected_signal == 1) selected_signal = 31; else if (selected_signal < 6) selected_signal += 25; else { @@ -704,7 +720,7 @@ if (selected_signal <= 16 and offset) selected_signal--; } } - else if (key == "down") { + else if (is_in(key, "down", "j")) { if (selected_signal == 31) selected_signal = 1; else if (selected_signal < 1 or selected_signal == 16) selected_signal = 1; else if (selected_signal > 26) selected_signal -= 25; @@ -715,11 +731,11 @@ if (selected_signal > 31) selected_signal = 31; } } - else if (key == "left" and selected_signal > 0 and selected_signal != 16) { + else if (is_in(key, "left", "h") and selected_signal > 0 and selected_signal != 16) { if (--selected_signal < 1) selected_signal = 31; else if (selected_signal == 16) selected_signal--; } - else if (key == "right" and selected_signal <= 31 and selected_signal != 16) { + else if (is_in(key, "right", "l") and selected_signal <= 31 and selected_signal != 16) { if (++selected_signal > 31) selected_signal = 1; else if (selected_signal == 16) selected_signal++; } @@ -903,10 +919,10 @@ exit(0); } } - else if (is_in(key, "down", "tab", "mouse_scroll_down")) { + else if (is_in(key, "down", "tab", "mouse_scroll_down", "j")) { if (++selected > 2) selected = 0; } - else if (is_in(key, "up", "shift_tab", "mouse_scroll_up")) { + else if (is_in(key, "up", "shift_tab", "mouse_scroll_up", "k")) { if (--selected < 0) selected = 2; } else { @@ -953,9 +969,11 @@ {"graph_symbol_proc", std::cref(Config::valid_graph_symbols_def)}, {"cpu_graph_upper", std::cref(Cpu::available_fields)}, {"cpu_graph_lower", std::cref(Cpu::available_fields)}, - {"cpu_sensor", std::cref(Cpu::available_sensors)} + {"cpu_sensor", std::cref(Cpu::available_sensors)}, + {"selected_battery", std::cref(Config::available_batteries)}, }; auto& tty_mode = Config::getB("tty_mode"); + auto& vim_keys = Config::getB("vim_keys"); if (max_items == 0) { for (const auto& cat : categories) { if ((int)cat.size() > max_items) max_items = cat.size(); @@ -1054,14 +1072,14 @@ else if (is_in(key, "escape", "q", "o", "backspace")) { return Closed; } - else if (is_in(key, "down", "mouse_scroll_down")) { + else if (is_in(key, "down", "mouse_scroll_down") or (vim_keys and key == "j")) { if (++selected > select_max or selected >= item_height) { if (page < pages - 1) page++; else if (pages > 1) page = 0; selected = 0; } } - else if (is_in(key, "up", "mouse_scroll_up")) { + else if (is_in(key, "up", "mouse_scroll_up") or (vim_keys and key == "k")) { if (--selected < 0) { if (page > 0) page--; else if (pages > 1) page = pages - 1; @@ -1089,12 +1107,12 @@ selected_cat = key.back() - '0' - 1; page = selected = 0; } - else if (is_in(key, "left", "right")) { + else if (is_in(key, "left", "right") or (vim_keys and is_in(key, "h", "l"))) { const auto& option = categories[selected_cat][item_height * page + selected][0]; if (selPred.test(isInt)) { const int mod = (option == "update_ms" ? 100 : 1); long value = Config::getI(option); - if (key == "right") value += mod; + if (key == "right" or (vim_keys and key == "l")) value += mod; else value -= mod; if (Config::intValid(option, to_string(value))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_tools.cpp new/btop-1.0.18/src/btop_tools.cpp --- old/btop-1.0.14/src/btop_tools.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_tools.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -321,9 +321,20 @@ return ss.str(); } - atomic_lock::atomic_lock(atomic<bool>& atom) : atom(atom) { + void atomic_wait(const atomic<bool>& atom, const bool old) noexcept { + while (atom.load(std::memory_order_relaxed) == old ) busy_wait(); + } + + void atomic_wait_for(const atomic<bool>& atom, const bool old, const uint64_t wait_ms) noexcept { + const uint64_t start_time = time_ms(); + while (atom.load(std::memory_order_relaxed) == old and (time_ms() - start_time < wait_ms)) sleep_ms(1); + } + + atomic_lock::atomic_lock(atomic<bool>& atom, bool wait) : atom(atom) { active_locks++; - while (not this->atom.compare_exchange_strong(this->not_true, true)); + if (wait) { + while (not this->atom.compare_exchange_strong(this->not_true, true)); + } else this->atom.store(true); } atomic_lock::~atomic_lock() { @@ -373,11 +384,9 @@ namespace Logger { using namespace Tools; - namespace { - std::atomic<bool> busy (false); - bool first = true; - const string tdf = "%Y/%m/%d (%T) | "; - } + std::atomic<bool> busy (false); + bool first = true; + const string tdf = "%Y/%m/%d (%T) | "; size_t loglevel; fs::path logfile; @@ -388,7 +397,7 @@ void log_write(const size_t level, const string& msg) { if (loglevel < level or logfile.empty()) return; - atomic_lock lck(busy); + atomic_lock lck(busy, true); std::error_code ec; try { if (fs::exists(logfile) and fs::file_size(logfile, ec) > 1024 << 10 and not ec) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/btop_tools.hpp new/btop-1.0.18/src/btop_tools.hpp --- old/btop-1.0.14/src/btop_tools.hpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/btop_tools.hpp 2021-10-19 17:29:57.000000000 +0200 @@ -269,14 +269,28 @@ string hostname(); string username(); - inline void atomic_wait(const atomic<bool>& atom, const bool old=true) noexcept { while (atom.load() == old) sleep_ms(1); } + static inline void busy_wait (void) { + #if defined __i386__ || defined __x86_64__ + __builtin_ia32_pause(); + #elif defined __ia64__ + __asm volatile("hint @pause" : : : "memory"); + #elif defined __sparc__ && (defined __arch64__ || defined __sparc_v9__) + __asm volatile("membar #LoadLoad" : : : "memory"); + #else + __asm volatile("" : : : "memory"); + #endif + } + + void atomic_wait(const atomic<bool>& atom, const bool old=true) noexcept; + + void atomic_wait_for(const atomic<bool>& atom, const bool old=true, const uint64_t wait_ms=0) noexcept; //* Waits for atomic<bool> to be false and sets it to true on construct, sets to false on destruct class atomic_lock { atomic<bool>& atom; bool not_true = false; public: - atomic_lock(atomic<bool>& atom); + atomic_lock(atomic<bool>& atom, bool wait=false); ~atomic_lock(); }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/btop-1.0.14/src/linux/btop_collect.cpp new/btop-1.0.18/src/linux/btop_collect.cpp --- old/btop-1.0.14/src/linux/btop_collect.cpp 2021-10-06 17:11:10.000000000 +0200 +++ new/btop-1.0.18/src/linux/btop_collect.cpp 2021-10-19 17:29:57.000000000 +0200 @@ -27,7 +27,7 @@ #include <ifaddrs.h> #include <net/if.h> -#ifndef STATIC_BUILD +#if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #include <pwd.h> #endif @@ -112,7 +112,7 @@ clkTck = 100; Logger::warning("Could not get system clock ticks per second. Defaulting to 100, processes cpu usage might be incorrect."); } - + //? Init for namespace Cpu if (not fs::exists(Cpu::freq_path) or access(Cpu::freq_path.c_str(), R_OK) == -1) Cpu::freq_path.clear(); Cpu::current_cpu.core_percent.insert(Cpu::current_cpu.core_percent.begin(), Shared::coreCount, {}); @@ -468,61 +468,99 @@ return core_map; } + struct battery { + fs::path base_dir, energy_now, energy_full, power_now, status, online; + string device_type; + bool use_energy = true; + }; + auto get_battery() -> tuple<int, long, string> { if (not has_battery) return {0, 0, ""}; - static fs::path bat_dir, energy_now_path, energy_full_path, power_now_path, status_path, online_path; - static bool use_energy = true; + static string auto_sel; + static unordered_flat_map<string, battery> batteries; //? Get paths to needed files and check for valid values on first run - if (bat_dir.empty() and has_battery) { + if (batteries.empty() and has_battery) { if (fs::exists("/sys/class/power_supply")) { for (const auto& d : fs::directory_iterator("/sys/class/power_supply")) { - if (const string dir_name = d.path().filename(); d.is_directory() and (dir_name.starts_with("BAT") or s_contains(str_to_lower(dir_name), "battery"))) { - bat_dir = d.path(); - break; + //? Only consider online power supplies of type Battery or UPS + //? see kernel docs for details on the file structure and contents + //? https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power + battery new_bat; + fs::path bat_dir; + try { + if (not d.is_directory() + or not fs::exists(d.path() / "type") + or not fs::exists(d.path() / "present") + or stoi(readfile(d.path() / "present")) != 1) + continue; + string dev_type = readfile(d.path() / "type"); + if (is_in(dev_type, "Battery", "UPS")) { + bat_dir = d.path(); + new_bat.base_dir = d.path(); + new_bat.device_type = dev_type; + } + } catch (...) { + //? skip power supplies not conforming to the kernel standard + continue; } + + if (fs::exists(bat_dir / "energy_now")) new_bat.energy_now = bat_dir / "energy_now"; + else if (fs::exists(bat_dir / "charge_now")) new_bat.energy_now = bat_dir / "charge_now"; + else new_bat.use_energy = false; + + if (fs::exists(bat_dir / "energy_full")) new_bat.energy_full = bat_dir / "energy_full"; + else if (fs::exists(bat_dir / "charge_full")) new_bat.energy_full = bat_dir / "charge_full"; + else new_bat.use_energy = false; + + if (not new_bat.use_energy and not fs::exists(bat_dir / "capacity")) { + continue; + } + + if (fs::exists(bat_dir / "power_now")) new_bat.power_now = bat_dir / "power_now"; + else if (fs::exists(bat_dir / "current_now")) new_bat.power_now = bat_dir / "current_now"; + + if (fs::exists(bat_dir / "AC0/online")) new_bat.online = bat_dir / "AC0/online"; + else if (fs::exists(bat_dir / "AC/online")) new_bat.online = bat_dir / "AC/online"; + + batteries[bat_dir.filename()] = new_bat; + Config::available_batteries.push_back(bat_dir.filename()); } } - if (bat_dir.empty()) { + if (batteries.empty()) { has_battery = false; return {0, 0, ""}; } - else { - if (fs::exists(bat_dir / "energy_now")) energy_now_path = bat_dir / "energy_now"; - else if (fs::exists(bat_dir / "charge_now")) energy_now_path = bat_dir / "charge_now"; - else use_energy = false; + } - if (fs::exists(bat_dir / "energy_full")) energy_full_path = bat_dir / "energy_full"; - else if (fs::exists(bat_dir / "charge_full")) energy_full_path = bat_dir / "charge_full"; - else use_energy = false; + auto& battery_sel = Config::getS("selected_battery"); - if (not use_energy and not fs::exists(bat_dir / "capacity")) { - has_battery = false; - return {0, 0, ""}; + if (auto_sel.empty()) { + for (auto& [name, bat] : batteries) { + if (bat.device_type == "Battery") { + auto_sel = name; + break; } - - if (fs::exists(bat_dir / "power_now")) power_now_path = bat_dir / "power_now"; - else if (fs::exists(bat_dir / "current_now")) power_now_path = bat_dir / "current_now"; - - if (fs::exists(bat_dir / "AC0/online")) online_path = bat_dir / "AC0/online"; - else if (fs::exists(bat_dir / "AC/online")) online_path = bat_dir / "AC/online"; } + if (auto_sel.empty()) auto_sel = batteries.begin()->first; } + auto& b = (battery_sel != "Auto" and batteries.contains(battery_sel) ? batteries.at(battery_sel) : batteries.at(auto_sel)); + int percent = -1; long seconds = -1; //? Try to get battery percentage - if (use_energy) { + if (b.use_energy) { try { - percent = round(100.0 * stoll(readfile(energy_now_path, "-1")) / stoll(readfile(energy_full_path, "1"))); + percent = round(100.0 * stoll(readfile(b.energy_now, "-1")) / stoll(readfile(b.energy_full, "1"))); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } if (percent < 0) { try { - percent = stoll(readfile(bat_dir / "capacity", "-1")); + percent = stoll(readfile(b.base_dir / "capacity", "-1")); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } @@ -533,9 +571,9 @@ } //? Get charging/discharging status - string status = str_to_lower(readfile(bat_dir / "status", "unknown")); - if (status == "unknown" and not online_path.empty()) { - const auto online = readfile(online_path, "0"); + string status = str_to_lower(readfile(b.base_dir / "status", "unknown")); + if (status == "unknown" and not b.online.empty()) { + const auto online = readfile(b.online, "0"); if (online == "1" and percent < 100) status = "charging"; else if (online == "1") status = "full"; else status = "discharging"; @@ -543,16 +581,16 @@ //? Get seconds to empty if (not is_in(status, "charging", "full")) { - if (use_energy and not power_now_path.empty()) { + if (b.use_energy and not b.power_now.empty()) { try { - seconds = round((double)stoll(readfile(energy_now_path, "0")) / stoll(readfile(power_now_path, "1")) * 3600); + seconds = round((double)stoll(readfile(b.energy_now, "0")) / stoll(readfile(b.power_now, "1")) * 3600); } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } } - if (seconds < 0 and fs::exists(bat_dir / "time_to_empty")) { + if (seconds < 0 and fs::exists(b.base_dir / "time_to_empty")) { try { - seconds = stoll(readfile(bat_dir / "time_to_empty", "0")) * 60; + seconds = stoll(readfile(b.base_dir / "time_to_empty", "0")) * 60; } catch (const std::invalid_argument&) { } catch (const std::out_of_range&) { } @@ -675,7 +713,7 @@ } if (not meminfo.good() or totalMem == 0) throw std::runtime_error("Could not get total memory size from /proc/meminfo"); - + return totalMem; } @@ -896,7 +934,11 @@ disks.at("swap").free_percent = mem.percent.at("swap_free").back(); } for (const auto& name : last_found) - if (not is_in(name, "/", "swap")) mem.disks_order.push_back(name); + #ifdef SNAPPED + if (not is_in(name, "/mnt", "swap")) mem.disks_order.push_back(name); + #else + if (not is_in(name, "/", "swap")) mem.disks_order.push_back(name); + #endif //? Get disks IO int64_t sectors_read, sectors_write, io_ticks; @@ -1350,7 +1392,7 @@ uid_user.clear(); pread.open(Shared::passwd_path); if (pread.good()) { - while (not pread.eof()) { + while (pread.good()) { getline(pread, r_user, ':'); pread.ignore(SSmax, ':'); getline(pread, r_uid, ':'); @@ -1418,7 +1460,7 @@ if (not pread.good()) continue; string uid; string line; - while (not pread.eof()) { + while (pread.good()) { getline(pread, line, ':'); if (line == "Uid") { pread.ignore(); @@ -1433,7 +1475,7 @@ new_proc.user = uid_user.at(uid); } else { - #ifndef STATIC_BUILD + #if !(defined(STATIC_BUILD) && defined(__GLIBC__)) try { struct passwd* udet; udet = getpwuid(stoi(uid)); @@ -1461,9 +1503,9 @@ uint64_t cpu_t = 0; try { for (;;) { - while (++x < next_x + offset) pread.ignore(SSmax, ' '); - getline(pread, short_str, ' '); + while (pread.good() and ++x < next_x + offset) pread.ignore(SSmax, ' '); if (not pread.good()) break; + else getline(pread, short_str, ' '); switch (x-offset) { case 3: //? Process state