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

use std::sync::{Arc, RwLock};

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

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

pub(crate) fn sysevent_sysx(pid: Pid, cache: &Arc<WorkerCache>, sandbox: &Arc<RwLock<Sandbox>>) {
    // This is ptrace(2) syscall exit stop.
    //
    // Verify with PTRACE_GET_SYSCALL_INFO.
    let info = match ptrace_get_syscall_info(pid) {
        Ok(info) if info.exit().is_none() => {
            // 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(_) => {
            // 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, sandbox) {
        Ok(_) => {
            let _ = ptrace_cont(pid, None);
        }
        Err(Errno::ESRCH) => {}
        Err(_) => {
            // Unexpected error during sysexit, terminate the process.
            let _ = kill(pid, Some(Signal::SIGKILL));
        }
    }
}
