-
Notifications
You must be signed in to change notification settings - Fork 415
Add an API for system processes #7681
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
Conversation
|
@keithc-ca could you please help in reviewing this PR? |
port/unix/omrsysinfo.c
Outdated
| DIR *dir = opendir("/proc"); | ||
| if (!dir) { | ||
| int32_t rc = findError(errno); | ||
| portLibrary->error_set_last_error(portLibrary, errno, rc); | ||
| Trc_PRT_sysinfo_get_open_file_count_failedOpeningProcFS(rc); | ||
| return -1; | ||
| } | ||
| struct dirent *entry; | ||
| char cmdline_path[PATH_MAX]; | ||
| char comm_path[PATH_MAX]; | ||
| char command[PATH_MAX]; | ||
| size_t bytes_read; | ||
| while ((entry = readdir(dir)) != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not strictly legal C code: declarations must be at the beginning of a block.
Please first update this so the additions follow the coding standard. Some examples of things that don't follow those guidelines:
- comparisons (
==and!=where the constant is not on the left - conditions with embedded assignments
- uninitialized local variables (e.g.
entry,bytes_readabove) - code should be indented one tab per level (not 8 spaces)
- missing comments on
#elseand#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made the changes given by you and updated PR
e45d7db to
ea48042
Compare
port/common/omrport.c
Outdated
| omrsysinfo_get_load_average, /* sysinfo_get_load_average */ | ||
| omrsysinfo_get_CPU_utilization, /* sysinfo_get_CPU_utilization */ | ||
| omrsysinfo_get_CPU_load, /* sysinfo_get_CPU_load */ | ||
| omrsysinfo_get_processes, /*sysinfo_get_processes */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space after /*.
port/common/omrsysinfo.c
Outdated
| uintptr_t | ||
| omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData) | ||
| { | ||
| return OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please indent with a tab instead of spaces.
port/unix/omrsysinfo.c
Outdated
| #include <ctype.h> | ||
| #include <stdint.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctype.his not needed (we can use juststrtoull()withoutisdigit())stdint.his already included viainttypes.h
port/unix/omrsysinfo.c
Outdated
| omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData) | ||
| { | ||
| #if defined(LINUX) | ||
| DIR *dir = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest moving this declaration to the point of initialization (after line 7581):
DIR *dir = opendir("/proc");
port/unix/omrsysinfo.c
Outdated
| char cmdline_path[PATH_MAX]; | ||
| char comm_path[PATH_MAX]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest we only need one of these buffers at a time (write the first path, try to read that file and only write the second path if necessary).
port/unix/omrsysinfo.c
Outdated
| portLibrary->file_close(portLibrary, file); | ||
| } | ||
| /* If cmdline is empty, try reading from comm */ | ||
| if (0 == bytes_read) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This must check for negative values:
if (bytes_read <= 0) {Likewise on line 7615.
port/unix/omrsysinfo.c
Outdated
| command[i] = ' '; | ||
| } | ||
| } | ||
| /* Call the callback function with the process ID and command */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
command should be NUL-terminated here:
command[bytes_read] = '\0';
port/unix/omrsysinfo.c
Outdated
| } | ||
| } | ||
| /* Call the callback function with the process ID and command */ | ||
| callback_result = callback((uintptr_t)strtoull(entry->d_name, NULL, 10), command, userData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use pid computed above:
callback_result = callback(pid, command, userData);8dcf87f to
a947338
Compare
port/common/omrport.tdf
Outdated
|
|
||
| TraceException=Trc_PRT_sysinfo_get_tmp_failed_str_covert Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_tmp: omrstr_convert() failed to convert unicode to modified utf8 with error code=%d" | ||
|
|
||
| TraceException=Trc_PRT_sysinfo_get_processes_failedOpeningProcFS Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_get_processes failed opening /proc = %d." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New tracepoints must be added to the end of the file; see https://github.com/eclipse-openj9/openj9/blob/master/doc/diagnostics/AddingTracepoints.md.
port/unix/omrsysinfo.c
Outdated
| omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData) | ||
| { | ||
| #if defined(LINUX) | ||
| struct dirent *entry = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Locals should be declared in the smallest block possible; entry should be declared where it is initialized (on line 7588).
Only these need to be declared here:
uintptr_t callback_result = 0;
DIR *dir = opendir("/proc");
port/unix/omrsysinfo.c
Outdated
| continue; | ||
| } | ||
| /* Convert name to pid, skipping non-numeric entries. */ | ||
| char *end = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not strictly legal in C to declare a local here.
port/unix/omrsysinfo.c
Outdated
| if (NULL == dir) { | ||
| int32_t rc = findError(errno); | ||
| portLibrary->error_set_last_error(portLibrary, errno, rc); | ||
| Trc_PRT_sysinfo_get_processes_failedOpeningProcFS(rc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No trailing spaces, please (here and line 7629).
port/unix/omrsysinfo.c
Outdated
| portLibrary->str_printf(portLibrary, path, sizeof(path), "/proc/%s/cmdline", entry->d_name); | ||
| file = portLibrary->file_open(portLibrary, path, EsOpenRead, 0); | ||
| if (0 != file) { | ||
| bytes_read = portLibrary->file_read(portLibrary, file, command, sizeof(command) - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may truncate commands which can be much longer than PATH_MAX (think megabytes).
62cef76 to
2626483
Compare
port/unix/omrsysinfo.c
Outdated
| #define ARG_MAX 2097152 | ||
| char path[PATH_MAX]; | ||
| char command[ARG_MAX]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not impose a fixed limit on the size of a command line. Greater than 4MB is unreasonable for a single stack frame.
|
This should not make reference to JFR; yes, it might be one of the first consumers of this new API, but this project aims to be language neutral. |
498f43a to
0d65739
Compare
port/unix/omrsysinfo.c
Outdated
| /* Try reading /proc/[pid]/cmdline. */ | ||
| portLibrary->str_printf(portLibrary, path, sizeof(path), "/proc/%s/cmdline", entry->d_name); | ||
| file = portLibrary->file_open(portLibrary, path, EsOpenRead, 0); | ||
| if (0 != file) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test should be file >= 0 (a negative value signals failure, 0 is a valid file descriptor); same for line 7640.
port/unix/omrsysinfo.c
Outdated
| for (;;) { | ||
| bytes_read = portLibrary->file_read(portLibrary, file, command, buffer_size - 1); | ||
| if (bytes_read < 0) { | ||
| break; | ||
| } | ||
| if (bytes_read == buffer_size - 1) { | ||
| /* Buffer may be too small, increase and retry. */ | ||
| new_size = buffer_size * 2; | ||
| new_command = (char *)portLibrary->mem_reallocate_memory( | ||
| portLibrary, | ||
| command, | ||
| new_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); | ||
| if (NULL == new_command) { | ||
| break; /* Stop resizing if allocation fails. */ | ||
| } | ||
| command = new_command; | ||
| buffer_size = new_size; | ||
| continue; | ||
| } | ||
| break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be extracted into a new function which can be reused on line 7641.
Note that the second and subsequent reads should not write to the beginning of command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked kernel header file and The result shows that TASK_COMM_LEN is defined as 16 in the kernel header file
278:#define TASK_COMM_LEN 16
1050: char comm[TASK_COMM_LEN];
1941: BUILD_BUG_ON(sizeof(buf) != TASK_COMM_LEN);
comm is a fixed-size buffer of 16 characters, so it doesn’t need resizing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any value in making assumptions about the size of /proc/N/comm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the reference I used: https://man7.org/linux/man-pages/man5/proc_pid_comm.5.html which specifies the command argument length as 16 characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please explain why a function that can handle arbitrarily long cmdline should not also be used for comm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have initialised buffer size of command in the beginning as 4096
cmdline argument length can be more than 4 KB so for that first I am trying to read command line and if the buffer is too small then I am resizing by doubling the buffer size until command line fits the buffer
but for comm argument fixed size is 16 characters so it doesn't need resizing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't suggesting it would need resizing. I am asking why it should be treated differently than reading cmdline, or equivalently, why should the code assume that comm is shorter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The /proc/[pid]/comm and /proc/[pid]/cmdline fields are treated differently because they serve distinct purposes. comm stores the process name with a fixed 16-character limit, while cmdline contains the full command-line arguments and can be much longer. first information is extracted from cmdline , but it is only available for user-space processes. If cmdline is unavailable, comm is used as a fallback to obtain the executable name.
if you have any other approach I would look into it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggested that the code "should be extracted into a new function which can be reused". Doing so avoids making any assumption about the size of the string in comm.
port/unix/omrsysinfo.c
Outdated
| return (uintptr_t)(intptr_t)rc; | ||
| } | ||
| /* Allocate initial buffer. */ | ||
| char *command = (char *)portLibrary->mem_allocate_memory(portLibrary, buffer_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not legal C code; variables must be declared at the beginning of a block.
|
Please correct the spelling of "API" in the commit summary line and update the title here (also removing "jfr:"). |
0d65739 to
ff79304
Compare
ff79304 to
978eec4
Compare
port/unix/omrsysinfo.c
Outdated
| intptr_t bytes_read = 0; | ||
| char *new_data = NULL; | ||
| for (;;) { | ||
| bytes_read = portLibrary->file_read(portLibrary, file, *data + total_bytes_read, buffer_size - 1 - total_bytes_read); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bytes_read should be declared here, the length argument should not include - 1 and the line should be split:
intptr_t bytes_read = portLibrary->file_read(
portLibrary,
file,
*data + total_bytes_read,
buffer_size - total_bytes_read);
port/unix/omrsysinfo.c
Outdated
| } | ||
| total_bytes_read += bytes_read; | ||
| /* Break if the buffer is large enough; otherwise, grow the buffer. */ | ||
| if (total_bytes_read < buffer_size - 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not subtract 1:
if (total_bytes_read < buffer_size) {
port/unix/omrsysinfo.c
Outdated
| } | ||
| /* Buffer may be too small, increase and retry. */ | ||
| buffer_size *= 2; | ||
| new_data = (char *)portLibrary->mem_reallocate_memory(portLibrary, *data, buffer_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split:
new_data = (char *)portLibrary->mem_reallocate_memory(
portLibrary,
*data,
buffer_size,
OMR_GET_CALLSITE(),
OMRMEM_CATEGORY_PORT_LIBRARY);
port/unix/omrsysinfo.c
Outdated
| *data = new_data; | ||
| *size = buffer_size; | ||
| } | ||
| (*data)[total_bytes_read] = '\0'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant - the caller will store the NUL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed all the subtraction logic (-1) but placed one in the beginning of the read_fully function, to make sure that there is at least one byte left for inserting the NULL character by the caller, in the edge case where the number of bytes read is exactly equal the size of the buffer. hope you are fine with that?
port/unix/omrsysinfo.c
Outdated
| omrsysinfo_get_processes(struct OMRPortLibrary *portLibrary, OMRProcessInfoCallback callback, void *userData) | ||
| { | ||
| #if defined(LINUX) | ||
| #define INITIAL_BUFFER_SIZE 4096 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this macro - it is only used once.
port/unix/omrsysinfo.c
Outdated
| return (uintptr_t)(intptr_t)rc; | ||
| } | ||
| /* Allocate initial buffer. */ | ||
| command = (char *)portLibrary->mem_allocate_memory(portLibrary, buffer_size, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be split:
command = (char *)portLibrary->mem_allocate_memory(
portLibrary,
buffer_size,
OMR_GET_CALLSITE(),
OMRMEM_CATEGORY_PORT_LIBRARY);
port/unix/omrsysinfo.c
Outdated
| bytes_read = read_fully(portLibrary, file, &command, &buffer_size); | ||
| portLibrary->file_close(portLibrary, file); | ||
| } | ||
| /* If cmdline is empty, try reading from comm. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment should be more similar to the one on line 7643:
/* If cmdline is empty, try reading /proc/[pid]/comm. */978eec4 to
ef21a27
Compare
port/unix/omrsysinfo.c
Outdated
| /* leave a byte for the caller in case it wants to NULL terminate it. */ | ||
| uintptr_t buffer_size = *size - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Subtracting one here is inappropriate; line 7578 guarantees that when this function succeeds, there is room for a NUL to be appended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ef21a27 to
8297bb4
Compare
The description and the commit message should say "Use cmdline" (the same tense should be used consistently). |
This has not been addressed. |
8297bb4 to
10f4e51
Compare
|
jenkins build all |
@harship04 There are compilation errors on Windows. Let me know once they are fixed, and I will relaunch the PR builds. |
|
@keithc-ca |
|
I think it would be
|
10f4e51 to
16cc79f
Compare
@babsingh , made the changes could you please trigger the Jenkins build |
|
jenkins build all |
16cc79f to
5410ec3
Compare
Use /proc filesystem to extract command line. Use cmdline for user space processes and comm for others.
5410ec3 to
43b06f1
Compare
|
jenkins build all |
Apply coding standards fix to function readFully for PR #7681
Use /proc filesystem to extract command line.
Use cmdline for user space processes and comm for others.