diff --git a/source/ucli/ucli-lib.cc b/source/ucli/ucli-lib.cc index 7381abd..3536d1e 100644 --- a/source/ucli/ucli-lib.cc +++ b/source/ucli/ucli-lib.cc @@ -3,13 +3,26 @@ #include #include #include - #include +#include +#include +#include +#include +#include + #include "symbol.h" #include "ucli.h" #include "unwind.h" + +#define BUF_LEN 4096 +#define WHITESPACE " \t\n\r" +#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +#define streq(a,b) (strcmp((a),(b)) == 0) + +unsigned long run_in_host = 0; + using namespace std; class pid_cmdline { @@ -194,4 +207,158 @@ void diag_printf_proc_chains(proc_chains_detail *proc_chains) { proc_chains->chains[i]); } } -} \ No newline at end of file +} + +int is_pid_1_has_environ(const char *field) { + bool done = false; + FILE *f = NULL; + int r = 0; + size_t l; + + assert(field); + + f = fopen("/proc/1/environ", "re"); + if (!f) + return 0; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + l = strlen(field); + + do { + char line[BUF_LEN]; + size_t i; + + for (i = 0; i < sizeof(line)-1; i++) { + int c; + + c = getc(f); + if ((c == EOF)) { + done = true; + break; + } else if (c == 0) + break; + + line[i] = c; + } + line[i] = 0; + + if (strneq(line, field, l) && line[l] == '=') { + r = 1; + goto out; + } + + } while (!done); + +out: + fclose(f); + return r; +} + +enum { + RUN_IN_HOST = 0, + RUN_IN_CONTAINER +}; + +int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) { + char status[BUF_LEN] = {0}; + char *t, *f; + size_t len; + int r; + + assert(terminator); + assert(filename); + assert(pattern); + assert(field); + + int fd = open(filename, O_RDONLY); + if (fd < 0) + return -errno; + + r = read(fd, &status, BUF_LEN - 1); + if (r < 0) + return r; + + t = status; + + do { + bool pattern_ok; + + do { + t = strstr(t, pattern); + if (!t) + return -ENOENT; + + /* Check that pattern occurs in beginning of line. */ + pattern_ok = (t == status || t[-1] == '\n'); + + t += strlen(pattern); + + } while (!pattern_ok); + + t += strspn(t, " \t"); + if (!*t) + return -ENOENT; + + } while (*t != ':'); + + t++; + + + if (*t) { + t += strspn(t, " \t"); + + /* Also skip zeros, because when this is used for + * capabilities, we don't want the zeros. This way the + * same capability set always maps to the same string, + * irrespective of the total capability set size. For + * other numbers it shouldn't matter. */ + t += strspn(t, "0"); + /* Back off one char if there's nothing but whitespace + and zeros */ + if (!*t || isspace(*t)) + t--; + } + + len = strcspn(t, terminator); + + f = strndup(t, len); + if (!f) + return -ENOMEM; + + *field = f; + return 0; +} + +static int detect_container_by_pid_2(void) { + char *s = NULL; + int r; + + r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s); + if (r >= 0) { + if (streq(s, "0")) + r = RUN_IN_HOST; + else + r = RUN_IN_CONTAINER; + } else if (r == -ENOENT) + r = RUN_IN_CONTAINER; + else { + printf("Failed to read /proc/2/status: %d\n", r); + r = RUN_IN_HOST; + } + + free(s); + return r; +} + +int check_in_host(void) +{ + int r; + + if (is_pid_1_has_environ("container")) + r = RUN_IN_CONTAINER; + else + r = detect_container_by_pid_2(); + + return r == RUN_IN_HOST; +} diff --git a/source/ucli/ucli.cc b/source/ucli/ucli.cc index aacb7b9..1a98843 100644 --- a/source/ucli/ucli.cc +++ b/source/ucli/ucli.cc @@ -2,10 +2,8 @@ * various_monitor cli 命令行工具 */ #include "ucli.h" - #include #include - #include static int task_info_extract(void *buf, unsigned int len, void *) { @@ -49,7 +47,10 @@ static int task_info_extract(void *buf, unsigned int len, void *) { tsk_info->task.state == 0 ? "R" : "D"); printk_task_brief(&tsk_info->task); - diag_printf_raw_stack(tsk_info->task.tgid, tsk_info->task.container_tgid, + // diag_printf_raw_stack(tsk_info->task.tgid, tsk_info->task.container_tgid, + // tsk_info->task.comm, &tsk_info->raw_stack); + printf("run_in_host: %d\n", run_in_host); + diag_printf_raw_stack(run_in_host ? tsk_info->task.tgid : tsk_info->task.container_tgid, tsk_info->task.container_tgid, tsk_info->task.comm, &tsk_info->raw_stack); diag_printf_kern_stack(&tsk_info->kern_stack); @@ -71,7 +72,7 @@ static void do_extract(char *buf, int len) { static void do_dump(const char *arg) { //!todo - static char variant_buf[512 * 1024 * 1024]; + static char variant_buf[256 * 1024 * 1024]; int len; int ret = 0; @@ -93,6 +94,8 @@ static void do_dump(const char *arg) { } int main(int argc, char *argv[]) { + run_in_host = check_in_host(); + static const struct option long_options[] = {{"help", no_argument, 0, 0}, {"report", no_argument, 0, 0}, {"pid", required_argument, 0, 0}, diff --git a/source/ucli/ucli.h b/source/ucli/ucli.h index f866b77..0aca6c1 100644 --- a/source/ucli/ucli.h +++ b/source/ucli/ucli.h @@ -124,6 +124,9 @@ void extract_variant_buffer(char *buf, unsigned int len, int (*func)(void *, unsigned int, void *), void *arg); +extern unsigned long run_in_host; +int check_in_host(void); + // all print fun void printk_task_brief(task_detail *detail); void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,