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 1 commit
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");
return NULL;

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

View check run for this annotation

Codecov / codecov/patch

src/linux/common.h#L120-L121

Added lines #L120 - L121 were not covered by tests
}

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

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

View check run for this annotation

Codecov / codecov/patch

src/linux/common.h#L126

Added line #L126 was not covered by tests

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

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

View check run for this annotation

Codecov / codecov/patch

src/linux/common.h#L129-L130

Added lines #L129 - L130 were not covered by tests
}

return proc_root;
}
20 changes: 10 additions & 10 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);

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

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L460

Added line #L460 was not covered by tests
set_error(EPROC);
FAIL;
}
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);

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

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L484

Added line #L484 was not covered by tests
set_error(EPROC);
FAIL;
}
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);

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

View check run for this annotation

Codecov / codecov/patch

src/linux/py_proc.h#L508

Added line #L508 was not covered by tests
set_error(EPROC);
FAIL;
}
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