mirror of
https://github.com/netdata/netdata.git
synced 2025-04-14 17:48:37 +00:00

* listening ipv6 sockets may be both ipv4 and ipv6, depending on the IPV6_ONLY flag * working libmnl ipv46 detection and added latency and retransmits from TCP_INFO * fix aggregations for rtt and retrans * code cleanup * code cleanup * code cleanup again * restore field renames * count namespaces * run namespaces in parallel * add libmnl to buildinfo * lock around safe_fork() * libmnl ports are in network byte order * posix spawn server for both executables and callback functions * local-sockets and network-viewer using the new spawn server * cleanup spawn servers sockets * spawn server stdin and stdout are linked to /dev/null * no need for spinlock in spawn server * empty all parameters * new spawn server is now used for plugins.d plugins * fix for environ * claiming script runs via the new spawn server * tc.plugin uses the new spawn server * analytics, buildinfo and cgroups.plugin use the new spawn server * cgroup-discovery uses the new spawn server * added ability to wait or kill spawned processes * removed old spawn server and now alert notifications use the new one * remove left-overs * hide spawn server internals; started working on windows version of the spawn server * fixes for windows * more windows work * more work on windows * added debug log to spawn server * fix compilation warnings * enable static threads on windows * running external plugins * working spawn server on windows * spawn server logs to collectoers.log * log windows last error together with errno * log updates * cleanup * decode_argv does not add an empty parameter * removed debug log * removed debug return * rework on close_range() * eliminate the need for waitid() * clear errno on the signal handler * added universal os_setproctitle() call to support FreeBSD too * os_get_pid_max() for windows and macos * isolate pids array from the rest of the code in apps.plugin so that it can be turned to a hashtable
151 lines
5 KiB
C
151 lines
5 KiB
C
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "apps_plugin.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define MAX_PROC_PID_LIMITS 8192
|
|
#define PROC_PID_LIMITS_MAX_OPEN_FILES_KEY "\nMax open files "
|
|
|
|
static inline kernel_uint_t get_proc_pid_limits_limit(char *buf, const char *key, size_t key_len, kernel_uint_t def) {
|
|
char *line = strstr(buf, key);
|
|
if(!line)
|
|
return def;
|
|
|
|
char *v = &line[key_len];
|
|
while(isspace(*v)) v++;
|
|
|
|
if(strcmp(v, "unlimited") == 0)
|
|
return 0;
|
|
|
|
return str2ull(v, NULL);
|
|
}
|
|
|
|
#if defined(__FreeBSD__) || defined(__APPLE__)
|
|
int read_proc_pid_limits_per_os(struct pid_stat *p, void *ptr __maybe_unused) {
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
|
static inline bool read_proc_pid_limits_per_os(struct pid_stat *p, void *ptr __maybe_unused) {
|
|
static char proc_pid_limits_buffer[MAX_PROC_PID_LIMITS + 1];
|
|
bool ret = false;
|
|
bool read_limits = false;
|
|
|
|
errno_clear();
|
|
proc_pid_limits_buffer[0] = '\0';
|
|
|
|
kernel_uint_t all_fds = pid_openfds_sum(p);
|
|
if(all_fds < p->limits.max_open_files / 2 && p->io_collected_usec > p->last_limits_collected_usec && p->io_collected_usec - p->last_limits_collected_usec <= 60 * USEC_PER_SEC) {
|
|
// too frequent, we want to collect limits once per minute
|
|
ret = true;
|
|
goto cleanup;
|
|
}
|
|
|
|
if(unlikely(!p->limits_filename)) {
|
|
char filename[FILENAME_MAX + 1];
|
|
snprintfz(filename, FILENAME_MAX, "%s/proc/%d/limits", netdata_configured_host_prefix, p->pid);
|
|
p->limits_filename = strdupz(filename);
|
|
}
|
|
|
|
int fd = open(p->limits_filename, procfile_open_flags, 0666);
|
|
if(unlikely(fd == -1)) goto cleanup;
|
|
|
|
ssize_t bytes = read(fd, proc_pid_limits_buffer, MAX_PROC_PID_LIMITS);
|
|
close(fd);
|
|
|
|
if(bytes <= 0)
|
|
goto cleanup;
|
|
|
|
// make it '\0' terminated
|
|
if(bytes < MAX_PROC_PID_LIMITS)
|
|
proc_pid_limits_buffer[bytes] = '\0';
|
|
else
|
|
proc_pid_limits_buffer[MAX_PROC_PID_LIMITS - 1] = '\0';
|
|
|
|
p->limits.max_open_files = get_proc_pid_limits_limit(proc_pid_limits_buffer, PROC_PID_LIMITS_MAX_OPEN_FILES_KEY, sizeof(PROC_PID_LIMITS_MAX_OPEN_FILES_KEY) - 1, 0);
|
|
if(p->limits.max_open_files == 1) {
|
|
// it seems a bug in the kernel or something similar
|
|
// it sets max open files to 1 but the number of files
|
|
// the process has open are more than 1...
|
|
// https://github.com/netdata/netdata/issues/15443
|
|
p->limits.max_open_files = 0;
|
|
ret = true;
|
|
goto cleanup;
|
|
}
|
|
|
|
p->last_limits_collected_usec = p->io_collected_usec;
|
|
read_limits = true;
|
|
|
|
ret = true;
|
|
|
|
cleanup:
|
|
if(p->limits.max_open_files)
|
|
p->openfds_limits_percent = (NETDATA_DOUBLE)all_fds * 100.0 / (NETDATA_DOUBLE)p->limits.max_open_files;
|
|
else
|
|
p->openfds_limits_percent = 0.0;
|
|
|
|
if(p->openfds_limits_percent > 100.0) {
|
|
if(!(p->log_thrown & PID_LOG_LIMITS_DETAIL)) {
|
|
char *line;
|
|
|
|
if(!read_limits) {
|
|
proc_pid_limits_buffer[0] = '\0';
|
|
line = "NOT READ";
|
|
}
|
|
else {
|
|
line = strstr(proc_pid_limits_buffer, PROC_PID_LIMITS_MAX_OPEN_FILES_KEY);
|
|
if (line) {
|
|
line++; // skip the initial newline
|
|
|
|
char *end = strchr(line, '\n');
|
|
if (end)
|
|
*end = '\0';
|
|
}
|
|
}
|
|
|
|
netdata_log_info(
|
|
"FDS_LIMITS: PID %d (%s) is using "
|
|
"%0.2f %% of its fds limits, "
|
|
"open fds = %"PRIu64 "("
|
|
"files = %"PRIu64 ", "
|
|
"pipes = %"PRIu64 ", "
|
|
"sockets = %"PRIu64", "
|
|
"inotifies = %"PRIu64", "
|
|
"eventfds = %"PRIu64", "
|
|
"timerfds = %"PRIu64", "
|
|
"signalfds = %"PRIu64", "
|
|
"eventpolls = %"PRIu64" "
|
|
"other = %"PRIu64" "
|
|
"), open fds limit = %"PRIu64", "
|
|
"%s, "
|
|
"original line [%s]",
|
|
p->pid, p->comm, p->openfds_limits_percent, all_fds,
|
|
p->openfds.files,
|
|
p->openfds.pipes,
|
|
p->openfds.sockets,
|
|
p->openfds.inotifies,
|
|
p->openfds.eventfds,
|
|
p->openfds.timerfds,
|
|
p->openfds.signalfds,
|
|
p->openfds.eventpolls,
|
|
p->openfds.other,
|
|
p->limits.max_open_files,
|
|
read_limits ? "and we have read the limits AFTER counting the fds"
|
|
: "but we have read the limits BEFORE counting the fds",
|
|
line);
|
|
|
|
p->log_thrown |= PID_LOG_LIMITS_DETAIL;
|
|
}
|
|
}
|
|
else
|
|
p->log_thrown &= ~PID_LOG_LIMITS_DETAIL;
|
|
|
|
return ret;
|
|
}
|
|
#endif // !__FreeBSD__ !__APPLE__
|
|
|
|
int read_proc_pid_limits(struct pid_stat *p, void *ptr) {
|
|
return read_proc_pid_limits_per_os(p, ptr) ? 1 : 0;
|
|
}
|