//
// Syd: rock-solid application kernel
// src/kernel/ptrace/event/sysx.rs: ptrace(2) syscall exit event handler
//
// Copyright (c) 2025 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

use std::sync::Arc;

use nix::{
    errno::Errno,
    sys::{
        ptrace,
        signal::{kill, Signal},
    },
    unistd::Pid,
};

use crate::{
    kernel::ptrace::handle_ptrace_sysexit, ptrace::ptrace_get_syscall_info, workers::WorkerCache,
};

pub(crate) fn sysevent_sysx(pid: Pid, cache: &Arc<WorkerCache>) {
    // This is ptrace syscall exit stop.
    //
    // SAFETY: Verify with PTRACE_GET_SYSCALL_INFO.
    let info = match ptrace_get_syscall_info(pid) {
        Ok(info) if info.exit().is_none() => {
            //unreachable!("BUG: Invalid syscall info returned by Linux: {info:?}")
            // trinity manages to reliably trigger this with op=0.
            // SAFETY: Failed to get syscall info but
            // process is still alive. Terminate!
            let _ = kill(pid, Some(Signal::SIGKILL));
            return;
        }
        Ok(info) => info,
        Err(Errno::ESRCH) => return,
        Err(_) => {
            // SAFETY: Failed to get syscall info but
            // process is still alive. Terminate!
            let _ = kill(pid, Some(Signal::SIGKILL));
            return;
        }
    };

    // Handle system call exit and continue if Ok.
    match handle_ptrace_sysexit(pid, info, cache) {
        Ok(_) => {
            let _ = ptrace::cont(pid, None);
        }
        Err(Errno::ESRCH) => {}
        Err(_) => {
            // SAFETY: Unexpected error during sysexit,
            // terminate the process.
            let _ = kill(pid, Some(Signal::SIGKILL));
        }
    }
}
