sysprofd: start on optimized getprocessinfo helper

Calling all the individual function calls to get process information would
be considerably inefficient, so we can coalesce a bunch of that and change
our process-model implementation (and proc source) to use this.
This commit is contained in:
Christian Hergert
2019-05-10 15:24:38 -07:00
parent c51e12c497
commit d6d4c0d140
2 changed files with 95 additions and 0 deletions

View File

@ -52,5 +52,25 @@
<method name="ListProcesses">
<arg name="processes" type="ai" direction="out"/>
</method>
<!--
GetProcessInfo:
@attributes: a comma separated string of attributes to load
Gets information about the processes on the system.
Attributes can be a comma separated list of the following:
- pid: (int32): the process identifier, always included
- cmdline: (string): Provides the command line
- maps: (string): Provide the contents of /proc/pid/maps
- statm: (string): Provide the contents of /proc/pid/statm
- mountinfo: (string): Provide the contents of/proc/pid/mountinfo
Returns: an array of vardict containing the requested attributs
-->
<method name="GetProcessInfo">
<arg name="attributes" type="s" direction="in"/>
<arg name="processes" type="aa{sv}" direction="out"/>
</method>
</interface>
</node>

View File

@ -188,12 +188,87 @@ ipc_service_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
return ret;
}
static void
add_pid_proc_file_to (gint pid,
const gchar *name,
GVariantDict *dict)
{
g_autofree gchar *path = NULL;
g_autofree gchar *contents = NULL;
gsize len;
g_assert (pid > -1);
g_assert (name != NULL);
g_assert (dict != NULL);
path = g_strdup_printf ("/proc/%d/%s", pid, name);
if (g_file_get_contents (path, &contents, &len, NULL))
g_variant_dict_insert (dict, name, "s", contents);
}
static gboolean
ipc_service_impl_handle_get_process_info (IpcService *service,
GDBusMethodInvocation *invocation,
const gchar *attributes)
{
GVariantBuilder builder;
g_autofree gint *processes = NULL;
gsize n_processes = 0;
gboolean want_statm;
gboolean want_cmdline;
gboolean want_maps;
gboolean want_mountinfo;
g_assert (IPC_IS_SERVICE (service));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_assert (attributes != NULL);
want_statm = !!strstr (attributes, "statm");
want_cmdline = !!strstr (attributes, "cmdline");
want_maps = !!strstr (attributes, "maps");
want_mountinfo = !!strstr (attributes, "mountinfo");
g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
if (helpers_list_processes (&processes, &n_processes))
{
for (guint i = 0; i < n_processes; i++)
{
gint pid = processes[i];
GVariantDict dict;
g_variant_dict_init (&dict, NULL);
g_variant_dict_insert (&dict, "pid", "i", pid);
if (want_statm)
add_pid_proc_file_to (pid, "statm", &dict);
if (want_cmdline)
add_pid_proc_file_to (pid, "cmdline", &dict);
if (want_maps)
add_pid_proc_file_to (pid, "maps", &dict);
if (want_mountinfo)
add_pid_proc_file_to (pid, "mountinfo", &dict);
g_variant_builder_add (&builder, "a{sv}", g_variant_dict_end (&dict));
}
}
ipc_service_complete_get_process_info (service, invocation, g_variant_builder_end (&builder));
return TRUE;
}
static void
init_service_iface (IpcServiceIface *iface)
{
iface->handle_list_processes = ipc_service_impl_handle_list_processes;
iface->handle_get_proc_file = ipc_service_impl_handle_get_proc_file;
iface->handle_perf_event_open = ipc_service_impl_handle_perf_event_open;
iface->handle_get_process_info = ipc_service_impl_handle_get_process_info;
}
G_DEFINE_TYPE_WITH_CODE (IpcServiceImpl, ipc_service_impl, IPC_TYPE_SERVICE_SKELETON,