Several micro fixes on the Linux implementation

Fix one segfault where some processes like “ls” live very briefly and
those may be catched up but at the time to read the cmdline the process
tree already disappeared. Also terminate the cmdline with \0.

I ran the application on my netbook, which doesn't have /proc/<PID>/comm
files... The code has been updated to read the short command from the
buffer.
This commit is contained in:
Mike Massonnet
2010-05-08 14:45:13 +02:00
committed by Mike Massonnet
parent a7465b61f4
commit e524915ac7

View File

@@ -107,7 +107,7 @@ static inline int get_pagesize ()
return pagesize; return pagesize;
} }
static void static gboolean
get_task_cmdline (Task *task) get_task_cmdline (Task *task)
{ {
FILE *file; FILE *file;
@@ -116,11 +116,13 @@ get_task_cmdline (Task *task)
gchar c; gchar c;
snprintf (filename, 96, "/proc/%i/cmdline", task->pid); snprintf (filename, 96, "/proc/%i/cmdline", task->pid);
if ((file = fopen (filename, "r")) == NULL)
return FALSE;
/* Read byte per byte until EOF */ /* Read full command byte per byte until EOF */
file = fopen (filename, "r");
for (i = 0; (c = fgetc (file)) != EOF && i < sizeof (task->cmdline) - 1; i++) for (i = 0; (c = fgetc (file)) != EOF && i < sizeof (task->cmdline) - 1; i++)
task->cmdline[i] = (c == '\0') ? ' ' : c; task->cmdline[i] = (c == '\0') ? ' ' : c;
task->cmdline[i] = '\0';
if (task->cmdline[i-1] == ' ') if (task->cmdline[i-1] == ' ')
task->cmdline[i-1] = '\0'; task->cmdline[i-1] = '\0';
fclose (file); fclose (file);
@@ -134,6 +136,8 @@ get_task_cmdline (Task *task)
task->cmdline[len+1] = ']'; task->cmdline[len+1] = ']';
task->cmdline[len+2] = '\0'; task->cmdline[len+2] = '\0';
} }
return TRUE;
} }
static void static void
@@ -171,7 +175,6 @@ get_task_details (guint pid, Task *task)
FILE *file; FILE *file;
gchar filename[96]; gchar filename[96];
gchar buffer[1024]; gchar buffer[1024];
gchar *p1, *p2;
snprintf (filename, 96, "/proc/%d/stat", pid); snprintf (filename, 96, "/proc/%d/stat", pid);
if ((file = fopen (filename, "r")) == NULL) if ((file = fopen (filename, "r")) == NULL)
@@ -180,21 +183,25 @@ get_task_details (guint pid, Task *task)
fgets (buffer, 1024, file); fgets (buffer, 1024, file);
fclose (file); fclose (file);
/* Scanning the short process name is unreliable with scanf when it contains spaces */ /* Scanning the short process name is unreliable with scanf when it contains
p1 = g_strrstr (buffer, "("); * spaces, retrieve it manually and fill the buffer */
p2 = g_strrstr (buffer, ")");
while (p1 <= p2)
{ {
*p1 = 'x'; gchar *p1, *po, *p2;
p1++; guint i = 0;
p1 = po = g_strstr_len (buffer, -1, "(");
p2 = g_strrstr (buffer, ")");
while (po <= p2)
{
if (po > p1 && po < p2)
{
task->name[i++] = *po;
task->name[i] = '\0';
}
*po = 'x';
po++;
}
} }
/* Retrieve the short name from the comm file */
snprintf (filename, 96, "/proc/%d/comm", pid);
file = fopen (filename, "r");
fscanf (file, "%255s", task->name);
fclose (file);
/* Parse the stat file */ /* Parse the stat file */
{ {
gchar dummy[256]; gchar dummy[256];
@@ -265,7 +272,8 @@ get_task_details (guint pid, Task *task)
} }
/* Read the full command line */ /* Read the full command line */
get_task_cmdline (task); if (!get_task_cmdline (task))
return FALSE;
return TRUE; return TRUE;
} }