tools/pylcc/pytool/oomkill.py (24 lines of code) (raw):
from pylcc.lbcBase import ClbcBase
from time import strftime
loadavg = "/proc/loadavg"
bpfPog = r"""
#include "lbc.h"
#define TASK_COMM_LEN 16
struct data_t {
u32 c_pid;
u32 p_pid;
u64 pages;
char c_comm[TASK_COMM_LEN];
char p_comm[TASK_COMM_LEN];
};
LBC_PERF_OUTPUT(e_out, struct data_t, 128);
SEC("kprobe/oom_kill_process")
int j_oom_kill_process(struct pt_regs *ctx)
{
struct oom_control* oc = (struct oom_control *)PT_REGS_PARM1(ctx);
struct task_struct* parent;
bpf_core_read(&parent, sizeof(parent), &oc->chosen);
struct data_t data = {};
data.c_pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&data.c_comm, TASK_COMM_LEN);
data.p_pid = BPF_CORE_READ(parent, pid);
bpf_core_read(&data.pages, sizeof(data.pages), &oc->totalpages);
bpf_core_read(&data.p_comm[0], TASK_COMM_LEN, &parent->comm[0]);
bpf_perf_event_output(ctx, &e_out, BPF_F_CURRENT_CPU, &data, sizeof(data));
return 0;
}
char _license[] SEC("license") = "GPL";
"""
class CeventOut(ClbcBase):
def __init__(self):
super(CeventOut, self).__init__("eventOut", bpf_str=bpfPog)
def _cb(self, cpu, data, size):
e = self.getMap('e_out', data, size)
with open(loadavg) as stats:
avgline = stats.read().rstrip()
print(("%s Triggered by PID %d (\"%s\"), OOM kill of PID %d (\"%s\")"
", %d pages, loadavg: %s") % (
strftime("%H:%M:%S"), e.c_pid, e.c_comm, e.p_pid, e.p_comm, e.pages, avgline))
def loop(self):
self.maps['e_out'].open_perf_buffer(self._cb)
try:
self.maps['e_out'].perf_buffer_poll()
except KeyboardInterrupt:
print("key interrupt.")
exit()
if __name__ == "__main__":
e = CeventOut()
e.loop()