Fetching the TTY name of a process is extremely expensive on darwin and
the call to devname accounts for 95% of htop's CPU usage when there is
high process turnover (this is mostly due to devname calling lstat,
which is incredibly slow). This can make htop unresponsive.
To mitigate this only set the process TTY name if the it is being
actively displayed (PROCESS_FLAG_TTY), which by default it is not
on darwin.
ProcessList_buildTree does not need any particular sort order for
children of the same process or roots. Switching these to the sort order
configured by the user produces sorted tree automatically, making repeat
sort unnecessary.
ProcessList_buildTreeBranch used to search for children with a linear
scan of the process table, which made tree build time quadratic in
process count. Pre-sorting the list by parent PID (if known) makes it
possible to select the correct slice by bisection much faster.
Separate `processes` (the vector owning the processes, sorted in
whatever order is needed right now internally) and `displayList` (a
vector referencing the processes in the same order they're to be
displayed).
Special-casing hidden processes does not serve any obvious purpose and
depends on the move from processes to processes2 which will be removed
in a later commit.
htop is a program which will be run on CHOST after cross-compilation;
CTARGET is only for a small number of cases where a program itself outputs
code (so you might cross-compile a compiler which spits out code for a third
architecture/platform).
We want to use AC_CANONICAL_HOST to check CHOST for the platform currently
being used to build htop.
The confusion around this issue was compounded by a mistake in autoconf-archive
which has since been fixed (AX_PTHREAD pulled it in incorrectly).
See: https://github.com/libstatgrab/libstatgrab/pull/131
See: https://github.com/fenrus75/powertop/pull/90#discussion_r705803725
Signed-off-by: Sam James <sam@gentoo.org>
This displays the same output as ps's -o emul, which is the system call
emulation environment, or ABI, in use. This will typically be FreeBSD
ELF32 or ELF64, but can also be Linux ELF32 or Linux ELF64 when running
Linux binaries under FreeBSD's Linuxulator binary compatibility layer.
The column width of 16 is chosen to match KI_EMULNAMELEN's value of 16,
most of which is normally used up as FreeBSD ELF32/64 is 13 characters.
On the help screen's depiction of the swap bar, the / separator between
used and cache should be coloured for consistency with the other bars.
I tried removing the coloured /s from the other bars to make them
consistent, but found that less visually appealing.
The system curses library can handle terminal size changes with
SIGWINCH without asking system calls to restart, which effectively
stops system calls with -1 and EINTR. An example is ncurses on
Linux systems.
One of these system calls is waitpid. While waiting for the lsof child
to complete, a badly timed SIGWINCH can interrupt the waitpid call,
effectively never clearing the state of the child, keeping the zombie
until htop exits.
Proof of Concept:
#include <unistd.h>
int main(void) {
close(1); close(2);
sleep(5);
return 0;
}
Compile this as a replacement "lsof" and put it into your path. Make
sure that it's called instead of the real lsof.
Press "l" to list open files and resize your terminal within the next
5 seconds. You will see that a zombie process is kept by htop when the
timeout finishes.
The parent process of htop might have set SIGCHLD to ignore, which can
be inherited by htop (Linux does this, OpenBSD resets to default).
If SIGCHLD is ignored then waitpid returns -1 which is not properly
handled by htop for lsof output.
Proof of Concept (Linux):
#include <signal.h>
#include <unistd.h>
int main(void) {
char *arg[] = { "htop", NULL };
signal(SIGCHLD, SIG_IGN);
execv("htop", arg);
return 1;
}
If you run htop with ignored SIGCHLD then pressing "l" always fails,
i.e. it is not possible to list open files even if lsof is installed.
It is possible to exceed the unsigned int data type on 64 bit systems
with enough available RAM. Use size_t in all places instead.
Proof of Concept: Create a 4 GB line in .htoprc file and run htop
$ dd if=/dev/zero bs=1024 count=4194304 | tr '\0' 'a' > ~/.htoprc
$ htop
Segmentation fault
Also avoid overflow of stack based "match" array in String_getToken.
Formatting the merged command string is now implemented in an platform
independent way. Drop the Process member getCommandStr designed for
overrides of individual platforms.
When reading a configuration file with the syntax previous to the
screens update Settings_defaultScreens() will add the default fields and
later ScreenSettings_readFields() will add the ones from the
configuration file. This will duplicate some fields and corrupt the
columns due to the boundless Command field.
The libunwind headers of LLVM are located in the subdirectory
/usr/include/libunwind. Search that subdirectory when the default
header test fails. Also extend the include path due to the transitive
include of `<__libunwind_config.h>`.
Closes: #894
With a size of 2 or 3 the grow factor does not reach 70% for one empty
entry. This will cause the following assert violation:
htop: Hashtable.c:236: void Hashtable_put(Hashtable *, ht_key_t, void *): Assertion `this->size > this->items' failed.
Due to the use of prime numbers Hashtable_remove used to never shrink
from some sizes. For example, a size 8191 hashtable would try to shrink
to 4095, which nextPrime would round back to 8191 instead of the
intended 4093. A factor of 3 is enough to allow every prime size used to
shrink to the previous one.
Not all batteries entries in /sys/class/power_supply start with either
BAT or AC, but might have device specific names, e.g. CMB1.
Detect the types of those entries and parse them accordingly.
Closes: #881
Fixes: 3e70de64 ("Code clean up for reading battery info")
Show a non highlighted string at the start of htop, not the failure
text.
Also the original fix only handled the text mode, not the bar mode.
Improves: 2977414d ("Discard stale information from DiskIO and NetworkIO meters")
Related: #860
Use C99 struct initialization, which also makes using calloc redundant.
htop: Process.c:1179: int Process_compareByKey_Base(const Process *, const Process *, ProcessField): Assertion `0 && "Process_compareByKey_Base: default key reached"' failed.