Running perfetto in detached mode

This document describes the --detach and --attach advanced operating modes of the perfetto cmdline client.

WARNING: The use of --detach and --attach is highly discouraged because of the risk of leaking tracing sessions and accidentally leaving tracing on for arbitrarily long periods of time.

TIP: If what you are looking for is just a way to grab a trace in background (e.g., while the USB cable / adb is disconnected) from the adb shell simply use --background.

Use case

By default the tracing service traced keeps the lifetime of a tracing session attached to the lifetime of the perfetto cmdline client that started it. This means that a killall perfetto or kill $PID_OF_PERFETTO is sufficient to guarantee that the tracing session is stopped.

There are rare occasions when this is undesirable; for example, this mode of operation was designed for the Traceur app (on-device tracing UI for Android).

When required by the user, Traceur needs to enable tracing in the background, possibly for very long periods of time. Because Traceur is not a persistent service (and even if it was, it could be still low-memory-killed), it cannot just use --background; this is because the Android framework kills any other process in the same process group when tearing down an app/service, and this would including killing forked perfetto client obtained via --background.

Operation

--detach=key decouples the lifetime of the cmdline client from the lifetime of the tracing session.

The key argument is an arbitrary string passed by the client to later re-identify the session using --attach=key.

Once detached, the cmdline client will exit (without forking any bg process) and the traced service will keep the tracing session alive. Because of the exit, a client that wants to use --detach needs to set the write_into_file option in the trace config, which transfers the responsibility of writing the output trace file to the service (see the examples section).

A detached session will run until either:

  • The session is later re-attached and stopped.
  • The time limit specified by the duration_ms argument in the trace config is reached.

--attach=key re-couples the lifetime of a new cmdline client invocation with an existing tracing session identified by key. For security reasons the service allows a client to re-attach to a tracing session only if the Unix UID of the re-attaching client matches the UID of the client that originally started the session and detached.

Overall --attach=key makes the perfetto cmdline client behave as if it was never detached. This means that:

  • sending a SIGKILL (or Ctrl-C) to the client will gracefully stop the tracing session.
  • If the duration_ms time limit is hit, the client will be informed by the service and exit soon after.

When re-attaching it is possible to also specify a further --stop argument. --stop will gracefully terminate the tracing session immediately after re-attaching (This is to avoid a race where SIGKILL is sent too early, before the client gets a chance to attach or even register the signal handler).

No other cmdline argument other than --stop can be passed when using --attach.

--is_detached=key can be used to check whether a detached session is running. The cmdline client will return quickly after the invocation with the following exit code:

  • 0 if the session identified by key exists and can be re-attached.
  • 1 in case of a general error (e.g. wrong cmdline, cannot reach the service).
  • 2 if no detached session with the given key is found.

Examples

Capturing a long trace in detached mode

echo '
write_into_file: true
# Long tracing mode, periodically flush the trace buffer into the trace file.
file_write_period_ms: 5000

buffers {
  # This buffer needs to be big enough just to hold data between two consecutive
  # |file_write_period|s (5s in this examples).
  size_kb: 16384
}

data_sources {
  config {
    name: "linux.ftrace"
    ftrace_config {
      ftrace_events: "sched_switch"
    }
  }
}
' | perfetto -c - --txt --detach=session1 -o /data/misc/perfetto-traces/trace

sleep 60

perfetto --attach=session1 --stop
# At this point the trace file is fully flushed into
# /data/misc/perfetto-traces/trace.

Start in detached ring-buffer mode. Later stop and save the ring buffer

echo '
write_into_file: true

# Specify an arbitrarily long flush period. Practically this means: never flush
# unless trace is stopped.
# TODO(primiano): an explicit no_periodic_flushes argument would be nicer. Maybe
# we could repurpose the 0 value?
file_write_period_ms: 1000000000

buffers {
  # This will be the size of the final trace.
  size_kb: 16384
}

data_sources {
  config {
    name: "linux.ftrace"
    ftrace_config {
      ftrace_events: "sched_switch"
    }
  }
}
' | perfetto -c - --txt --detach=session2 -o /data/misc/perfetto-traces/trace

# Wait for user input, or some critical event to happen.

perfetto --attach=session2 --stop

# At this point the trace file is saved into
# /data/misc/perfetto-traces/trace.

Start tracing with a time limit. Later re-attach and wait for the end

echo '
duration_ms: 10000
write_into_file: true

buffers {
  size_kb: 16384
}

data_sources {
  config {
    name: "linux.ftrace"
    ftrace_config {
      ftrace_events: "sched_switch"
    }
  }
}
' | perfetto -c - --txt --detach=session3 -o /data/misc/perfetto-traces/trace

sleep 3
perfetto --attach=session3
# The cmdline client will stay up for 7 more seconds and then terminate.