[nemiver/profiler] Basic support of profiling running processes



commit a758ea69e8d907e97073c58e49f16e9875079549
Author: Fabien Parent <parent f gmail com>
Date:   Sat Jul 28 22:25:38 2012 +0200

    Basic support of profiling running processes

 configure.ac                                       |    5 ++-
 src/persp/profperspective/nmv-prof-perspective.cc  |    3 +
 src/profengine/Makefile.am                         |    8 ++--
 src/profengine/nmv-perf-engine.cc                  |   22 ++++++++--
 src/profengine/nmv-perf-server.cc                  |   47 +++++++++++++++++---
 src/profengine/org.gnome.nemiver.profiler.conf.in  |   14 ++++++
 .../org.gnome.nemiver.profiler.service.in          |    4 ++
 7 files changed, 87 insertions(+), 16 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 939edad..32c9df0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -410,11 +410,12 @@ if test x$exec_prefix = xNONE ; then
         exec_prefix=$prefix ;
 fi
 NEMIVER_LIBDIR=`eval echo $libdir`
+NEMIVER_BINDIR=`eval echo $bindir`
 
 AC_SUBST(NEMIVER_INCLUDE_DIR)
 AC_SUBST(NEMIVER_LIB_DIR_NAME)
 AC_SUBST(NEMIVER_LIBDIR)
-
+AC_SUBST(NEMIVER_BINDIR)
 
 if test x$ENABLE_GCC_SYMBOLS_VISIBILITY = xyes && test x$host_cpu != xx86_64 ; then
     AC_DEFINE(HAS_GCC_VISIBILITY_SUPPORT,1,[gcc visibility support])
@@ -484,6 +485,8 @@ src/Makefile
   src/dbgengine/varlistwalker.conf
   src/profengine/Makefile
   src/profengine/perfengine.conf
+  src/profengine/org.gnome.nemiver.profiler.service
+  src/profengine/org.gnome.nemiver.profiler.conf
   src/confmgr/Makefile
   src/confmgr/gconfmgr.conf
   src/confmgr/gsettingsmgr.conf
diff --git a/src/persp/profperspective/nmv-prof-perspective.cc b/src/persp/profperspective/nmv-prof-perspective.cc
index 1b70185..f9c9f33 100644
--- a/src/persp/profperspective/nmv-prof-perspective.cc
+++ b/src/persp/profperspective/nmv-prof-perspective.cc
@@ -631,6 +631,9 @@ ProfPerspective::attach_to_process (unsigned a_pid)
 
     THROW_IF_FAIL (throbber);
     throbber->start ();
+
+    THROW_IF_FAIL (recording_action_group);
+    recording_action_group->set_sensitive (true);
 }
 
 void
diff --git a/src/profengine/Makefile.am b/src/profengine/Makefile.am
index 6385e74..9408476 100644
--- a/src/profengine/Makefile.am
+++ b/src/profengine/Makefile.am
@@ -41,11 +41,11 @@ nmvperfserver= NEMIVER_MODULES_DIR@
 nmvperfserver_LDADD= NEMIVERPROFPERSP_LIBS@ \
 $(abs_top_builddir)/src/common/libnemivercommon.la
 
-#service_DATA=org.gnome.nemiver.profiler.service.in
-#servicedir=
+service_DATA=org.gnome.nemiver.profiler.service
+servicedir=$(datadir)/dbus-1/system-services
 
-#policy_DATA=org.gnome.nemiver.profiler.policy.in
-#policydir=
+bus_DATA=org.gnome.nemiver.profiler.conf.in
+busdir=/etc/dbus-1/system.d/
 
 INCLUDES= NEMIVERCOMMON_CFLAGS@ @NEMIVERPROFPERSP_CFLAGS@ \
 -DENABLE_NLS=1 -DDATADIR=\"${datadir}\" \
diff --git a/src/profengine/nmv-perf-engine.cc b/src/profengine/nmv-perf-engine.cc
index 030f82c..df2bc07 100644
--- a/src/profengine/nmv-perf-engine.cc
+++ b/src/profengine/nmv-perf-engine.cc
@@ -64,6 +64,7 @@ struct PerfEngine::Priv {
     sigc::signal<void, const UString&> record_done_signal;
     sigc::signal<void, const UString&, const UString&> symbol_annotated_signal;
 
+    bool is_using_prof_server;
     Glib::RefPtr<Gio::DBus::Connection> server_connection;
     Glib::RefPtr<Gio::DBus::Proxy> proxy;
 
@@ -75,6 +76,7 @@ struct PerfEngine::Priv {
         perf_stderr_fd (0),
         perf_stdout_channel (0),
         call_graph (0),
+        is_using_prof_server (false),
         server_connection (0),
         proxy (0)
     {
@@ -85,7 +87,7 @@ struct PerfEngine::Priv {
     init ()
     {
         server_connection =
-            Gio::DBus::Connection::get_sync (Gio::DBus::BUS_TYPE_SESSION);
+            Gio::DBus::Connection::get_sync (Gio::DBus::BUS_TYPE_SYSTEM);
         THROW_IF_FAIL (server_connection);
 
         proxy = Gio::DBus::Proxy::create_sync (server_connection,
@@ -389,16 +391,21 @@ PerfEngine::attach_to_pid (int a_pid)
     std::vector<Glib::ustring> options;
 
     Glib::Variant<int> pid_param = Glib::Variant<int>::create (a_pid);
+    Glib::Variant<int> uid_param = Glib::Variant<int>::create (getuid ());
+    Glib::Variant<int> gid_param = Glib::Variant<int>::create (a_pid);
     Glib::Variant<std::vector<Glib::ustring> > options_param =
         Glib::Variant<std::vector<Glib::ustring> >::create (options);
 
     std::vector<Glib::VariantBase> parameters;
     parameters.push_back (pid_param);
+    parameters.push_back (uid_param);
+    parameters.push_back (gid_param);
     parameters.push_back (options_param);
 
     Glib::VariantContainerBase parameters_variant =
         Glib::VariantContainerBase::create_tuple (parameters);
 
+    m_priv->is_using_prof_server = true;
     m_priv->proxy->call
         ("AttachToPID",
          sigc::mem_fun (*m_priv, &PerfEngine::Priv::on_detached_from_process),
@@ -495,6 +502,7 @@ PerfEngine::record (const std::vector<UString> &a_argv)
     argv.push_back (m_priv->record_filepath);
     argv.insert (argv.end (), a_argv.begin (), a_argv.end ());
 
+    m_priv->is_using_prof_server = false;
     bool is_launched = common::launch_program (argv,
                                                m_priv->perf_pid,
                                                m_priv->master_pty_fd,
@@ -523,8 +531,13 @@ void
 PerfEngine::stop_recording ()
 {
     THROW_IF_FAIL (m_priv);
-    THROW_IF_FAIL (m_priv->perf_pid);
-    kill(m_priv->perf_pid, SIGINT);
+
+    if (m_priv->is_using_prof_server) {
+        m_priv->proxy->call_sync ("DetachFromProcess");
+    } else {
+        THROW_IF_FAIL (m_priv->perf_pid);
+        kill (m_priv->perf_pid, SIGINT);
+    }
 }
 
 void
@@ -541,7 +554,7 @@ PerfEngine::report (const UString &a_data_file)
 
     THROW_IF_FAIL (m_priv);
     m_priv->record_filepath = a_data_file;
-
+    m_priv->is_using_prof_server = false;
     bool is_launched = common::launch_program (argv,
                                                m_priv->perf_pid,
                                                m_priv->master_pty_fd,
@@ -580,6 +593,7 @@ PerfEngine::annotate_symbol (const UString &a_symbol_name)
     argv.push_back (m_priv->record_filepath);
     argv.push_back (a_symbol_name);
 
+    m_priv->is_using_prof_server = false;
     bool is_launched = common::launch_program (argv,
                                                m_priv->perf_pid,
                                                m_priv->master_pty_fd,
diff --git a/src/profengine/nmv-perf-server.cc b/src/profengine/nmv-perf-server.cc
index 68baf5c..8f737f0 100644
--- a/src/profengine/nmv-perf-server.cc
+++ b/src/profengine/nmv-perf-server.cc
@@ -50,10 +50,14 @@ static const char *const NMV_DBUS_PROFILER_SERVER_INTROSPECTION_DATA =
     "  <interface name='org.gnome.nemiver.profiler'>"
     "    <method name='AttachToPID'>"
     "        <arg type='i' name='pid' direction='in' />"
+    "        <arg type='i' name='uid' direction='in' />"
+    "        <arg type='i' name='gid' direction='in' />"
 //    "        <arg type='u' name='cookie' direction='in' />"
     "        <arg type='as' name='arguments' direction='in' />"
     "        <arg type='s' name='data_filepath' direction='out' />"
     "    </method>"
+    "    <method name='DetachFromProcess'>"
+    "    </method>"
     "  </interface>"
     "</node>";
 
@@ -84,7 +88,7 @@ struct PerfServer::Priv {
     int perf_stderr_fd;
 
     Priv () :
-//        subject (polkit_system_bus_name_new ("org.gnome.nemiver")),
+//        subject (polkit_system_bus_name_new ("org.gnome.Nemiver")),
         bus_id (0),
         registration_id (0),
         introspection_data (0),
@@ -99,8 +103,9 @@ struct PerfServer::Priv {
     }
 
     bool
-    on_wait_for_record_to_exit (const Glib::RefPtr<Gio::DBus::MethodInvocation>
-                                    &a_invocation,
+    on_wait_for_record_to_exit (int a_uid, int a_gid,
+                                Glib::RefPtr<Gio::DBus::MethodInvocation>
+                                    a_invocation,
                                 Glib::ustring a_report_filepath)
     {
         int status = 0;
@@ -114,14 +119,22 @@ struct PerfServer::Priv {
             perf_stdout_fd = 0;
             perf_stderr_fd = 0;
 
+            NEMIVER_TRY;
+
             Glib::Variant<Glib::ustring> perf_data =
                 Glib::Variant<Glib::ustring>::create (a_report_filepath);
 
             Glib::VariantContainerBase response =
                 Glib::VariantContainerBase::create_tuple (perf_data);
 
+            chown (a_report_filepath.c_str (), a_uid, a_gid);
+
+            std::cout << "Saving report to " << a_report_filepath << std::endl;
+
             a_invocation->return_value (response);
 
+            NEMIVER_CATCH_NOX;
+
             return false;
         }
 
@@ -129,7 +142,7 @@ struct PerfServer::Priv {
     }
 
     void
-    on_new_request (const Glib::RefPtr<Gio::DBus::Connection>&,
+    on_new_request (const Glib::RefPtr<Gio::DBus::Connection> &a_connection,
                     const Glib::ustring&,
                     const Glib::ustring&,
                     const Glib::ustring&,
@@ -140,15 +153,22 @@ struct PerfServer::Priv {
     {
         NEMIVER_TRY;
 
+        THROW_IF_FAIL (a_connection);
         THROW_IF_FAIL (a_invocation);
 
         if(a_request_name == "AttachToPID") {
             Glib::Variant<int> pid_param;
+            Glib::Variant<int> uid_param;
+            Glib::Variant<int> gid_param;
             Glib::Variant<std::vector<Glib::ustring> > options_param;
             a_parameters.get_child (pid_param);
-            a_parameters.get_child (options_param, 1);
+            a_parameters.get_child (uid_param, 1);
+            a_parameters.get_child (gid_param, 2);
+            a_parameters.get_child (options_param, 3);
 
             int pid = pid_param.get ();
+            int uid = uid_param.get ();
+            int gid = gid_param.get ();
             std::vector<Glib::ustring> options (options_param.get ());
             for (std::vector<Glib::ustring>::iterator iter = options.begin ();
                  iter != options.end ();
@@ -176,6 +196,8 @@ struct PerfServer::Priv {
             argv.push_back (filepath.get ());
             argv.insert (argv.end (), options.begin (), options.end ());
 
+            std::cout << "Launching perf with pid: " << pid << std::endl;
+
             bool is_launched =
                 common::launch_program (argv,
                                         perf_pid,
@@ -185,15 +207,26 @@ struct PerfServer::Priv {
 
             THROW_IF_FAIL (is_launched);
 
+            std::cout << "Perf started" << std::endl;
+
             Glib::RefPtr<Glib::MainContext> context =
                 Glib::MainContext::get_default ();
             context->signal_idle ().connect
-                (sigc::bind<const Glib::RefPtr<Gio::DBus::MethodInvocation>, Glib::ustring>
+                (sigc::bind<int, int,
+                            Glib::RefPtr<Gio::DBus::MethodInvocation>,
+                            Glib::ustring>
                         (sigc::mem_fun (*this,
                          &PerfServer::Priv::on_wait_for_record_to_exit),
+                 uid, gid,
                  a_invocation,
                  filepath.get ()));
         }
+        else if (a_request_name == "DetachFromProcess") {
+            kill (perf_pid, SIGINT);
+
+            Glib::VariantContainerBase response;
+            a_invocation->return_value (response);
+        }
         else
         {
             Gio::DBus::Error error
@@ -211,7 +244,7 @@ struct PerfServer::Priv {
             (NMV_DBUS_PROFILER_SERVER_INTROSPECTION_DATA);
 
         bus_id = Gio::DBus::own_name
-            (Gio::DBus::BUS_TYPE_SESSION,
+            (Gio::DBus::BUS_TYPE_SYSTEM,
              NMV_BUS_NAME,
              sigc::mem_fun (*this, &PerfServer::Priv::on_bus_acquired),
              sigc::mem_fun (*this, &PerfServer::Priv::on_name_acquired),
diff --git a/src/profengine/org.gnome.nemiver.profiler.conf.in b/src/profengine/org.gnome.nemiver.profiler.conf.in
new file mode 100644
index 0000000..946ac30
--- /dev/null
+++ b/src/profengine/org.gnome.nemiver.profiler.conf.in
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+
+  <policy user="root">
+    <allow own="org.gnome.nemiver.profiler"/>
+  </policy>
+
+  <policy context="default">
+    <allow send_interface="org.gnome.nemiver.profiler"/>
+  </policy>
+
+</busconfig>
diff --git a/src/profengine/org.gnome.nemiver.profiler.service.in b/src/profengine/org.gnome.nemiver.profiler.service.in
new file mode 100644
index 0000000..d55c1d5
--- /dev/null
+++ b/src/profengine/org.gnome.nemiver.profiler.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.gnome.nemiver.profiler
+Exec= NEMIVER_BINDIR@/nmvperfserver
+User=root



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]