Skip to content

Commit

Permalink
Fix giampaolo#1276: [AIX] use getargs to get process cmdline
Browse files Browse the repository at this point in the history
  • Loading branch information
Arnon Yaari committed Apr 30, 2019
1 parent 0ba30fd commit 314e598
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 30 deletions.
20 changes: 10 additions & 10 deletions psutil/_psaix.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,20 +358,13 @@ def __init__(self, pid):
self._procfs_path = get_procfs_path()

def oneshot_enter(self):
self._proc_name_and_args.cache_activate(self)
self._proc_basic_info.cache_activate(self)
self._proc_cred.cache_activate(self)

def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate(self)
self._proc_basic_info.cache_deactivate(self)
self._proc_cred.cache_deactivate(self)

@wrap_exceptions
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)

@wrap_exceptions
@memoize_when_activated
def _proc_basic_info(self):
Expand All @@ -386,8 +379,10 @@ def _proc_cred(self):
def name(self):
if self.pid == 0:
return "swapper"
# note: this is limited to 15 characters
return self._proc_name_and_args()[0].rstrip("\x00")
# pr_fname is PRFNSZ (16) characters long
# if the name is longer than 16 characters, pr_fname will not
# be NULL-terminated, so we truncate it here
return cext.proc_name(self.pid, self._procfs_path)[:16]

@wrap_exceptions
def exe(self):
Expand Down Expand Up @@ -415,7 +410,12 @@ def exe(self):

@wrap_exceptions
def cmdline(self):
return self._proc_name_and_args()[1].split(' ')
try:
return cext.proc_args(self.pid) or ['']
except OSError as err:
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
raise

@wrap_exceptions
def create_time(self):
Expand Down
79 changes: 59 additions & 20 deletions psutil/_psutil_aix.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@

#include <Python.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/limits.h>
#include <sys/proc.h>
#include <sys/sysinfo.h>
#include <sys/procfs.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/thread.h>
#include <sys/types.h>
#include <fcntl.h>
#include <utmp.h>
#include <utmpx.h>
Expand Down Expand Up @@ -134,45 +135,81 @@ psutil_proc_basic_info(PyObject *self, PyObject *args) {


/*
* Return process name and args as a Python tuple.
* Return process name as a Python string.
*/
static PyObject *
psutil_proc_name_and_args(PyObject *self, PyObject *args) {
psutil_proc_name(PyObject *self, PyObject *args) {
int pid;
char path[100];
psinfo_t info;
const char *procfs_path;
PyObject *py_name = NULL;
PyObject *py_args = NULL;
PyObject *py_retlist = NULL;

if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path))
return NULL;
sprintf(path, "%s/%i/psinfo", procfs_path, pid);
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;

py_name = PyUnicode_DecodeFSDefault(info.pr_fname);
if (!py_name)
return PyUnicode_DecodeFSDefault(info.pr_fname);
}


/*
* Return process command line arguments as a Python list
*/
static PyObject *
psutil_proc_args(PyObject *self, PyObject *args) {
int pid;
PyObject *py_retlist = PyList_New(0);
PyObject *py_arg = NULL;
struct procsinfo procbuf;
long arg_max;
char *argbuf = NULL;
char *curarg = NULL;
int ret;

if (py_retlist == NULL)
return NULL;
if (!PyArg_ParseTuple(args, "i", &pid))
goto error;
py_args = PyUnicode_DecodeFSDefault(info.pr_psargs);
if (!py_args)
arg_max = sysconf(_SC_ARG_MAX);
argbuf = malloc(arg_max);
if (!argbuf)
goto error;
py_retlist = Py_BuildValue("OO", py_name, py_args);
if (!py_retlist)

procbuf.pi_pid = pid;
ret = getargs(&procbuf, sizeof(struct procinfo), argbuf, ARG_MAX);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
Py_DECREF(py_name);
Py_DECREF(py_args);
}

curarg = argbuf;
/* getargs will always append an extra NULL to end the arg list,
* even if the buffer is not big enough (even though it is supposed
* to be) so the following 'while' is safe */
while (*curarg != '\0') {
py_arg = PyUnicode_DecodeFSDefault(curarg);
if (!py_arg)
goto error;
if (PyList_Append(py_retlist, py_arg))
goto error;
Py_DECREF(py_arg);
curarg = strchr(curarg, '\0') + 1;
}

return py_retlist;

error:
Py_XDECREF(py_name);
Py_XDECREF(py_args);
if (argbuf != NULL)
free(argbuf);
Py_XDECREF(py_retlist);
Py_XDECREF(py_arg);
return NULL;
}



#ifdef CURR_VERSION_THREAD

/*
Expand Down Expand Up @@ -880,8 +917,10 @@ PsutilMethods[] =
// --- process-related functions
{"proc_basic_info", psutil_proc_basic_info, METH_VARARGS,
"Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"},
{"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS,
"Return process name and args."},
{"proc_name", psutil_proc_name, METH_VARARGS,
"Return process name."},
{"proc_args", psutil_proc_args, METH_VARARGS,
"Return process command line arguments."},
{"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS,
"Return process user and system CPU times."},
{"proc_cred", psutil_proc_cred, METH_VARARGS,
Expand Down
16 changes: 16 additions & 0 deletions psutil/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,12 +724,28 @@ def test_cmdline(self):
else:
raise

def test_long_cmdline(self):
create_exe(TESTFN)
self.addCleanup(safe_rmpath, TESTFN)
cmdline = [TESTFN] + (["0123456789"] * 20)
sproc = get_test_subprocess(cmdline)
p = psutil.Process(sproc.pid)
self.assertEqual(p.cmdline(), cmdline)

def test_name(self):
sproc = get_test_subprocess(PYTHON_EXE)
name = psutil.Process(sproc.pid).name().lower()
pyexe = os.path.basename(os.path.realpath(sys.executable)).lower()
assert pyexe.startswith(name), (pyexe, name)

def test_long_name(self):
long_name = TESTFN + ("0123456789" * 2)
create_exe(long_name)
self.addCleanup(safe_rmpath, long_name)
sproc = get_test_subprocess(long_name)
p = psutil.Process(sproc.pid)
self.assertEqual(p.name(), os.path.basename(long_name))

# XXX
@unittest.skipIf(SUNOS, "broken on SUNOS")
@unittest.skipIf(AIX, "broken on AIX")
Expand Down

0 comments on commit 314e598

Please sign in to comment.