diff --git a/src/libsysprof/sysprof-recording-private.h b/src/libsysprof/sysprof-recording-private.h index 4fbbbe44..a77f8eee 100644 --- a/src/libsysprof/sysprof-recording-private.h +++ b/src/libsysprof/sysprof-recording-private.h @@ -22,18 +22,70 @@ #include -#include "sysprof-instrument.h" +#include "sysprof-diagnostic-private.h" +#include "sysprof-instrument-private.h" #include "sysprof-recording.h" #include "sysprof-spawnable.h" G_BEGIN_DECLS +typedef enum _SysprofRecordingCommand +{ + SYSPROF_RECORDING_COMMAND_STOP = 1, +} SysprofRecordingCommand; + +struct _SysprofRecording +{ + GObject parent_instance; + + /* Used to calculate the duration of the recording */ + gint64 start_time; + gint64 end_time; + + /* Used to calculate event count */ + SysprofCaptureStat stat; + + /* Diagnostics that may be added by instruments during the recording. + * Some may be fatal, meaning that they stop the recording when the + * diagnostic is submitted. That can happen in situations like + * miss-configuration or failed authorization. + */ + GListStore *diagnostics; + + /* If we are spawning a process as part of this recording, this + * is the SysprofSpawnable used to spawn the process. + */ + SysprofSpawnable *spawnable; + + /* This is where all of the instruments will write to. They are + * expected to do this from the main-thread only. To work from + * additional threads they need to proxy that state to the + * main thread for writing. + */ + SysprofCaptureWriter *writer; + + /* An array of SysprofInstrument that are part of this recording */ + GPtrArray *instruments; + + /* A DexFiber that will complete when the recording has finished, + * been stopped, or failed. + */ + DexFuture *fiber; + + /* The channel is used ot send state change messages to the fiber + * from outside of the fiber. + */ + DexChannel *channel; + + /* The process we have spawned, if any */ + GSubprocess *subprocess; +}; + SysprofRecording *_sysprof_recording_new (SysprofCaptureWriter *writer, SysprofSpawnable *spawnable, SysprofInstrument **instruments, guint n_instruments); void _sysprof_recording_start (SysprofRecording *self); -SysprofCaptureWriter *_sysprof_recording_writer (SysprofRecording *self); SysprofSpawnable *_sysprof_recording_get_spawnable (SysprofRecording *self); DexFuture *_sysprof_recording_add_file (SysprofRecording *self, const char *path, @@ -43,6 +95,8 @@ void _sysprof_recording_add_file_data (SysprofRecording *s const char *contents, gssize length, gboolean compress); +void _sysprof_recording_follow_fork (SysprofRecording *self, + int pid); void _sysprof_recording_diagnostic (SysprofRecording *self, const char *domain, const char *format, @@ -52,4 +106,10 @@ void _sysprof_recording_error (SysprofRecording *s const char *format, ...) G_GNUC_PRINTF (3, 4); +static inline SysprofCaptureWriter * +_sysprof_recording_writer (const SysprofRecording *self) +{ + return self->writer; +} + G_END_DECLS diff --git a/src/libsysprof/sysprof-recording.c b/src/libsysprof/sysprof-recording.c index 5dc090ab..a57ace2c 100644 --- a/src/libsysprof/sysprof-recording.c +++ b/src/libsysprof/sysprof-recording.c @@ -26,62 +26,8 @@ #include -#include "sysprof-diagnostic-private.h" -#include "sysprof-instrument-private.h" #include "sysprof-recording-private.h" -typedef enum _SysprofRecordingCommand -{ - SYSPROF_RECORDING_COMMAND_STOP = 1, -} SysprofRecordingCommand; - -struct _SysprofRecording -{ - GObject parent_instance; - - /* Used to calculate the duration of the recording */ - gint64 start_time; - gint64 end_time; - - /* Used to calculate event count */ - SysprofCaptureStat stat; - - /* Diagnostics that may be added by instruments during the recording. - * Some may be fatal, meaning that they stop the recording when the - * diagnostic is submitted. That can happen in situations like - * miss-configuration or failed authorization. - */ - GListStore *diagnostics; - - /* If we are spawning a process as part of this recording, this - * is the SysprofSpawnable used to spawn the process. - */ - SysprofSpawnable *spawnable; - - /* This is where all of the instruments will write to. They are - * expected to do this from the main-thread only. To work from - * additional threads they need to proxy that state to the - * main thread for writing. - */ - SysprofCaptureWriter *writer; - - /* An array of SysprofInstrument that are part of this recording */ - GPtrArray *instruments; - - /* A DexFiber that will complete when the recording has finished, - * been stopped, or failed. - */ - DexFuture *fiber; - - /* The channel is used ot send state change messages to the fiber - * from outside of the fiber. - */ - DexChannel *channel; - - /* The process we have spawned, if any */ - GSubprocess *subprocess; -}; - enum { PROP_0, PROP_DURATION, @@ -94,12 +40,10 @@ G_DEFINE_FINAL_TYPE (SysprofRecording, sysprof_recording, G_TYPE_OBJECT) static GParamSpec *properties[N_PROPS]; static DexFuture * -_sysprof_recording_spawn (SysprofRecording *self, - SysprofSpawnable *spawnable, +_sysprof_recording_spawn (SysprofSpawnable *spawnable, GSubprocess **subprocess) { g_autoptr(GError) error = NULL; - const char *identifier; DexFuture *ret; g_assert (SYSPROF_IS_SPAWNABLE (spawnable)); @@ -109,12 +53,6 @@ _sysprof_recording_spawn (SysprofRecording *self, if (!(*subprocess = sysprof_spawnable_spawn (spawnable, &error))) return dex_future_new_for_error (g_steal_pointer (&error)); - if ((identifier = g_subprocess_get_identifier (*subprocess))) - { - int pid = atoi (identifier); - dex_await (_sysprof_instruments_process_started (self->instruments, self, pid), NULL); - } - ret = dex_subprocess_wait_check (*subprocess); dex_async_pair_set_cancel_on_discard (DEX_ASYNC_PAIR (ret), FALSE); return ret; @@ -197,7 +135,7 @@ sysprof_recording_fiber (gpointer user_data) /* If we need to spawn a subprocess, do it now */ if (self->spawnable != NULL) - monitor = _sysprof_recording_spawn (self, self->spawnable, &self->subprocess); + monitor = _sysprof_recording_spawn (self->spawnable, &self->subprocess); else monitor = dex_future_new_infinite (); @@ -564,14 +502,6 @@ _sysprof_recording_get_spawnable (SysprofRecording *self) return self->spawnable; } -SysprofCaptureWriter * -_sysprof_recording_writer (SysprofRecording *self) -{ - g_return_val_if_fail (SYSPROF_IS_RECORDING (self), NULL); - - return self->writer; -} - typedef struct _AddFile { SysprofCaptureWriter *writer; @@ -966,3 +896,13 @@ sysprof_recording_get_subprocess (SysprofRecording *self) return self->subprocess; } + +void +_sysprof_recording_follow_fork (SysprofRecording *self, + int pid) +{ + g_return_if_fail (SYSPROF_IS_RECORDING (self)); + g_return_if_fail (pid > 0); + + dex_future_disown (_sysprof_instruments_process_started (self->instruments, self, pid)); +} diff --git a/src/libsysprof/sysprof-sampler.c b/src/libsysprof/sysprof-sampler.c index a0aa8a06..4a906dbe 100644 --- a/src/libsysprof/sysprof-sampler.c +++ b/src/libsysprof/sysprof-sampler.c @@ -105,7 +105,8 @@ sysprof_sampler_perf_event_stream_cb (const SysprofPerfEvent *event, guint cpu, gpointer user_data) { - SysprofCaptureWriter *writer = user_data; + SysprofRecording *recording = user_data; + SysprofCaptureWriter *writer = _sysprof_recording_writer (recording); gsize offset; gint64 time; @@ -148,10 +149,7 @@ sysprof_sampler_perf_event_stream_cb (const SysprofPerfEvent *event, event->fork.ptid, event->fork.tid); - /* - * TODO: We should add support for "follow fork" of the GPid if we are - * targetting it. - */ + _sysprof_recording_follow_fork (recording, event->fork.tid); break; @@ -248,7 +246,6 @@ static DexFuture * sysprof_sampler_prepare_fiber (gpointer user_data) { Prepare *prepare = user_data; - SysprofCaptureWriter *writer; g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GPtrArray) futures = NULL; g_autoptr(GError) error = NULL; @@ -290,7 +287,6 @@ sysprof_sampler_prepare_fiber (gpointer user_data) */ n_cpu = g_get_num_processors (); futures = g_ptr_array_new_with_free_func (dex_unref); - writer = _sysprof_recording_writer (prepare->recording); try_again: attr.sample_type = PERF_SAMPLE_IP @@ -332,8 +328,8 @@ try_again: -1, 0, sysprof_sampler_perf_event_stream_cb, - sysprof_capture_writer_ref (writer), - (GDestroyNotify)sysprof_capture_writer_unref)); + g_object_ref (prepare->recording), + g_object_unref)); if (!dex_await (dex_future_allv ((DexFuture **)futures->pdata, futures->len), &error)) {