Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(linux): improved container support #217

Merged
merged 2 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
2024-xx-xx v3.6.1

Improve support for Python processes running in containers.

Bugfix: fixed a bug with the MOJO binary format that caused the line end
position to wrongly be set to a non-zero value for CPython < 3.11, where line
end information is not actually available.
Expand Down
23 changes: 23 additions & 0 deletions src/linux/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ptrace.h>

#include "../error.h"
#include "../hints.h"
#include "../stats.h"


Expand Down Expand Up @@ -109,3 +111,24 @@

return fp;
}


// ----------------------------------------------------------------------------
static inline char *
proc_root(pid_t pid, char * file) {
if (file[0] != '/') {
log_e("File path is not absolute"); // GCOV_EXCL_START
return NULL; // GCOV_EXCL_STOP

Check warning on line 121 in src/linux/common.h

View check run for this annotation

Codecov / codecov/patch

src/linux/common.h#L121

Added line #L121 was not covered by tests
}

char * proc_root = calloc(1, strlen(file) + 24);
if (!isvalid(proc_root))
return NULL; // GCOV_EXCL_LINE

if (sprintf(proc_root, "/proc/%d/root%s", pid, file) < 0) {
free(proc_root); // GCOV_EXCL_START
return NULL; // GCOV_EXCL_STOP

Check warning on line 130 in src/linux/common.h

View check run for this annotation

Codecov / codecov/patch

src/linux/common.h#L130

Added line #L130 was not covered by tests
}

return proc_root;
}
26 changes: 13 additions & 13 deletions src/linux/py_proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,16 +455,16 @@
// The first memory map of the executable
if (!isvalid(pd->maps[MAP_BIN].path) && strcmp(pd->exe_path, pathname) == 0) {
map = &(pd->maps[MAP_BIN]);
map->path = strndup(pathname, strlen(pathname));
map->path = proc_root(self->pid, pathname);
if (!isvalid(map->path)) {
log_ie("Cannot duplicate path name");
log_e("Cannot get proc root path for %s", pathname); // GCOV_EXCL_START
set_error(EPROC);
FAIL;
FAIL; // GCOV_EXCL_STOP

Check warning on line 462 in src/linux/py_proc.h

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L462

Added line #L462 was not covered by tests
}
map->file_size = _file_size(pathname);
map->file_size = _file_size(map->path);
map->base = (void *) lower;
map->size = upper - lower;
map->has_symbols = success(_py_proc__analyze_elf(self, pathname, (void *) lower));
map->has_symbols = success(_py_proc__analyze_elf(self, map->path, (void *) lower));
if (map->has_symbols) {
map->bss_base = self->map.bss.base;
map->bss_size = self->map.bss.size;
Expand All @@ -479,13 +479,13 @@
int has_symbols = success(_py_proc__analyze_elf(self, pathname, (void *) lower));
if (has_symbols) {
map = &(pd->maps[MAP_LIBSYM]);
map->path = strndup(pathname, strlen(pathname));
map->path = proc_root(self->pid, pathname);
if (!isvalid(map->path)) {
log_ie("Cannot duplicate path name");
log_e("Cannot get proc root path for %s", pathname); // GCOV_EXCL_START
set_error(EPROC);
FAIL;
FAIL; // GCOV_EXCL_STOP

Check warning on line 486 in src/linux/py_proc.h

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L486

Added line #L486 was not covered by tests
}
map->file_size = _file_size(pathname);
map->file_size = _file_size(map->path);
map->base = (void *) lower;
map->size = upper - lower;
map->has_symbols = TRUE;
Expand All @@ -503,13 +503,13 @@
unsigned int v;
if (sscanf(needle, "libpython%u.%u", &v, &v) == 2) {
map = &(pd->maps[MAP_LIBNEEDLE]);
map->path = needle_path = strndup(pathname, strlen(pathname));
map->path = needle_path = proc_root(self->pid, pathname);

Check warning on line 506 in src/linux/py_proc.h

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L506

Added line #L506 was not covered by tests
if (!isvalid(map->path)) {
log_ie("Cannot duplicate path name");
log_e("Cannot get proc root path for %s", pathname); // GCOV_EXCL_START
set_error(EPROC);
FAIL;
FAIL; // GCOV_EXCL_STOP

Check warning on line 510 in src/linux/py_proc.h

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L510

Added line #L510 was not covered by tests
}
map->file_size = _file_size(pathname);
map->file_size = _file_size(map->path);

Check warning on line 512 in src/linux/py_proc.h

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L512

Added line #L512 was not covered by tests
map->base = (void *) lower;
map->size = upper - lower;
map->has_symbols = FALSE;
Expand Down
21 changes: 7 additions & 14 deletions src/py_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,14 @@ _get_version_from_executable(char * binary, int * major, int * minor, int * patc
#endif

fp = _popen(cmd, "r");
if (!isvalid(fp)) {
set_error(EPROC);
if (!isvalid(fp))
FAIL;
}

while (fgets(version, sizeof(version) - 1, fp) != NULL) {
if (sscanf(version, "Python %d.%d.%d", major, minor, patch) == 3)
SUCCESS;
}

set_error(EPROC);
FAIL;
} /* _get_version_from_executable */

Expand All @@ -129,37 +126,34 @@ _get_version_from_filename(char * filename, const char * needle, int * major, in
#if defined PL_LINUX /* LINUX */
char * base = filename;
char * end = base + strlen(base);
size_t needle_len = strlen(needle);

while (base < end) {
base = strstr(base, needle);
if (!isvalid(base)) {
break;
}
if (sscanf(base + strlen(needle), "%u.%u", major, minor) == 2) {
base += needle_len;
if (sscanf(base, "%u.%u", major, minor) == 2) {
SUCCESS;
}
}

#elif defined PL_WIN /* WIN */
// Assume the library path is of the form *.python3[0-9]+[.]dll
int n = strlen(filename);
if (n < 10) {
set_error(EPROC);
if (n < 10)
FAIL;
}

char * p = filename + n - 1;
while (*(p--) != 'n' && p > filename);
p++;
*major = *(p++) - '0';
if (*major != 3) {
set_error(EPROC);
if (*major != 3)
FAIL;
}

if (sscanf(p,"%d.dll", minor) == 1) {
if (sscanf(p,"%d.dll", minor) == 1)
SUCCESS;
}

#elif defined PL_MACOS /* MAC */
char * ver_needle = strstr(filename, "3.");
Expand All @@ -169,7 +163,6 @@ _get_version_from_filename(char * filename, const char * needle, int * major, in

#endif

set_error(EPROC);
FAIL;
} /* _get_version_from_filename */

Expand Down
Loading