|
@@ -7458,7 +7458,19 @@ __perf_event_exit_task(struct perf_event *child_event,
|
|
|
struct perf_event_context *child_ctx,
|
|
|
struct task_struct *child)
|
|
|
{
|
|
|
- perf_remove_from_context(child_event, true);
|
|
|
+ /*
|
|
|
+ * Do not destroy the 'original' grouping; because of the context
|
|
|
+ * switch optimization the original events could've ended up in a
|
|
|
+ * random child task.
|
|
|
+ *
|
|
|
+ * If we were to destroy the original group, all group related
|
|
|
+ * operations would cease to function properly after this random
|
|
|
+ * child dies.
|
|
|
+ *
|
|
|
+ * Do destroy all inherited groups, we don't care about those
|
|
|
+ * and being thorough is better.
|
|
|
+ */
|
|
|
+ perf_remove_from_context(child_event, !!child_event->parent);
|
|
|
|
|
|
/*
|
|
|
* It can happen that the parent exits first, and has events
|