···1212var events_ringbuf = bpf.Map.RingBuffer("events", 10, 0).init();
1313var diagnostics_ringbuf = bpf.Map.RingBuffer("diagnostics", 10, 0).init();
14141515+// This one isn't needed by userspace, we use it to keep track of which
1616+// processes we've seen a `clone_enter`/`clone3_enter` from so that we can know
1717+// which `clone_exit`/`clone3_exit` calls to record.
1818+//
1919+// Remember that you can see a `clone`/`clone3` when a *thread* is created,
2020+// and you can only tell apart a thread from a process when you have access
2121+// to the clone flags that are passed in as an argument. Once you're on the
2222+// exit side of the tracepoint you no longer have access to those flags, so
2323+// you need some other way to tell whether or not to record the event.
2424+var clone_seen_map = bpf.Map.HashMap("seen", bridge.Pid, bool, 10, 0).init();
2525+1526const raw_tp_enter = bpf.RawTracepoint{ .side = .enter };
1627const raw_tp_exit = bpf.RawTracepoint{ .side = .exit };
1728···146157 // unsigned long, tls)
147158148159 const clone_flags = args[0];
149149- if (is_new_process(clone_flags)) {
150150- const meta = new_event_meta();
151151- if (events_ringbuf.reserve(bridge.Event)) |reserved| {
152152- reserved.ptr.* = .{ .fork_start = .{ .meta = meta } };
153153- reserved.submit();
154154- } else {
155155- if (diagnostics_ringbuf.reserve(bridge.Diagnostic)) |r| {
156156- var buf: [64]u8 = [_]u8{0} ** 64;
157157- const str = "failed to reserve space in ringbuf";
158158- @memcpy(buf[0..str.len], str);
159159- r.ptr.* = .{ .meta = meta, .tp = .clone_enter, .err = bridge.CollectorError.RingbufReserve, .msg = buf };
160160- r.submit();
161161- }
162162- }
163163- }
160160+ clone_enter_common(clone_flags, .clone_enter);
164161}
165162166163fn handle_clone3_enter(args: *const [6]u64) void {
···182179 }
183180 return;
184181 }
182182+ clone_enter_common(flags, .clone3_enter);
183183+}
184184+185185+fn clone_enter_common(flags: u64, tp_kind: bridge.TracepointKind) void {
185186 if (is_new_process(flags)) {
186187 const meta = new_event_meta();
187188 if (events_ringbuf.reserve(bridge.Event)) |reserved| {
···192193 var buf: [64]u8 = [_]u8{0} ** 64;
193194 const str = "failed to reserve space in ringbuf";
194195 @memcpy(buf[0..str.len], str);
195195- r.ptr.* = .{ .meta = meta, .tp = .clone3_enter, .err = bridge.CollectorError.RingbufReserve, .msg = buf };
196196+ r.ptr.* = .{ .meta = meta, .tp = tp_kind, .err = bridge.CollectorError.RingbufReserve, .msg = buf };
196197 r.submit();
198198+ return;
197199 }
198200 }
201201+ clone_seen_map.update(.any, meta.pid, true);
199202 }
200203}
201204