summaryrefslogtreecommitdiff
path: root/psutil/_psutil_sunos.c
diff options
context:
space:
mode:
authoralxchk <alxchk@gmail.com>2018-03-11 18:48:13 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2018-03-11 09:48:13 -0700
commit66edd7ade36c871a15f2cb230ae1c054f842555a (patch)
tree7c71109b266e6f18688751ee28ff12542b222047 /psutil/_psutil_sunos.c
parent2ffb0ecc5e41c5486056fcd00aca274d77858860 (diff)
downloadpsutil-66edd7ade36c871a15f2cb230ae1c054f842555a.tar.gz
Try to extract argv[] from process address space first (#1220)
* Try to extract argv[] from process address space first * Add comments and OOM exception * Handle the case with empty array
Diffstat (limited to 'psutil/_psutil_sunos.c')
-rw-r--r--psutil/_psutil_sunos.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c
index c6673642..4d38a342 100644
--- a/psutil/_psutil_sunos.c
+++ b/psutil/_psutil_sunos.c
@@ -116,6 +116,58 @@ psutil_proc_basic_info(PyObject *self, PyObject *args) {
);
}
+/*
+ * Join array of C strings to C string with delemiter dm.
+ * Omit empty records.
+ */
+static int
+cstrings_array_to_string(char **joined, char ** array, size_t count, char dm) {
+ int i;
+ size_t total_length = 0;
+ size_t item_length = 0;
+ char *result = NULL;
+ char *last = NULL;
+
+ if (!array || !joined)
+ return 0;
+
+ for (i=0; i<count; i++) {
+ if (!array[i])
+ continue;
+
+ item_length = strlen(array[i]) + 1;
+ total_length += item_length;
+ }
+
+ if (!total_length) {
+ return 0;
+ }
+
+ result = malloc(total_length);
+ if (!result) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ result[0] = '\0';
+ last = result;
+
+ for (i=0; i<count; i++) {
+ if (!array[i])
+ continue;
+
+ item_length = strlen(array[i]);
+ memcpy(last, array[i], item_length);
+ last[item_length] = dm;
+
+ last += item_length + 1;
+ }
+
+ result[total_length-1] = '\0';
+ *joined = result;
+
+ return total_length;
+}
/*
* Return process name and args as a Python tuple.
@@ -125,6 +177,10 @@ psutil_proc_name_and_args(PyObject *self, PyObject *args) {
int pid;
char path[1000];
psinfo_t info;
+ size_t argc;
+ int joined;
+ char **argv;
+ char *argv_plain;
const char *procfs_path;
PyObject *py_name = NULL;
PyObject *py_args = NULL;
@@ -139,12 +195,37 @@ psutil_proc_name_and_args(PyObject *self, PyObject *args) {
py_name = PyUnicode_DecodeFSDefault(info.pr_fname);
if (!py_name)
goto error;
- py_args = PyUnicode_DecodeFSDefault(info.pr_psargs);
+
+ /* SunOS truncates arguments to length PRARGSZ, very likely args are truncated.
+ * The only way to retrieve full command line is to parse process memory */
+ if (info.pr_argc && strlen(info.pr_psargs) == PRARGSZ-1) {
+ argv = psutil_read_raw_args(info, procfs_path, &argc);
+ if (argv) {
+ joined = cstrings_array_to_string(&argv_plain, argv, argc, ' ');
+ if (joined > 0) {
+ py_args = PyUnicode_DecodeFSDefault(argv_plain);
+ free(argv_plain);
+ } else if (joined < 0) {
+ goto error;
+ }
+
+ psutil_free_cstrings_array(argv, argc);
+ }
+ }
+
+ /* If we can't read process memory or can't decode the result
+ * then return args from /proc. */
+ if (!py_args)
+ py_args = PyUnicode_DecodeFSDefault(info.pr_psargs);
+
+ /* Both methods has been failed. */
if (!py_args)
goto error;
+
py_retlist = Py_BuildValue("OO", py_name, py_args);
if (!py_retlist)
goto error;
+
Py_DECREF(py_name);
Py_DECREF(py_args);
return py_retlist;