mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
* Preserve Unicode in thread unraisable messages Keep the callable representation as WTF-8 for unraisable hooks and audit callbacks. Preserve the existing String entry point and stderr fallback; this does not claim lossless stderr rendering. Assisted-by: OpenAI Codex:model unavailable * Use the WTF-8 string conversion constructor Use the existing From<&str> implementation to copy the message prefix without changing Unicode semantics. Assisted-by: OpenAI Codex:model unavailable * Preserve cross-interpreter marshal error causes Wrap failures from existing code/function serialization helpers as NotShareableError, matching the CPython 3.15 marshal boundary while retaining the original exception cause. No new test C API or lifecycle behavior. Assisted-by: OpenAI Codex:model-unavailable * Enforce syslog interpreter boundaries and sync queue cleanup Reject subinterpreter openlog/closelog before audit or host mutation, and reject implicit syslog opening after audit when the process logger is not already open, matching CPython 3.15 guard placement and error text. Already-open logging and setlogmask remain unchanged. Migrate concurrent/interpreters/_queues.py through scripts/update_lib to CPython d220409a13b77de7a6c30abe16ea90db01528edc, removing unused eager pickle import and exception targets. Native serialization imports pickle on demand; module import timing and debug locals may nevertheless differ. No new fixtures or interpreter lifecycle mechanisms are introduced. Assisted-by: OpenAI Codex:model version unavailable
171 lines
5.2 KiB
Rust
171 lines
5.2 KiB
Rust
// spell-checker:ignore logoption openlog setlogmask upto NDELAY ODELAY
|
|
|
|
pub(crate) use syslog::module_def;
|
|
|
|
#[pymodule(name = "syslog")]
|
|
mod syslog {
|
|
use crate::vm::{
|
|
Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
|
builtins::{PyStr, PyStrRef},
|
|
convert::ToPyException,
|
|
utils::ToCString,
|
|
};
|
|
use rustpython_host_env::syslog as host_syslog;
|
|
|
|
#[pyattr]
|
|
use host_syslog::{
|
|
LOG_ALERT, LOG_AUTH, LOG_CONS, LOG_CRIT, LOG_DAEMON, LOG_DEBUG, LOG_EMERG, LOG_ERR,
|
|
LOG_INFO, LOG_KERN, LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5,
|
|
LOG_LOCAL6, LOG_LOCAL7, LOG_LPR, LOG_MAIL, LOG_NDELAY, LOG_NEWS, LOG_NOTICE, LOG_NOWAIT,
|
|
LOG_ODELAY, LOG_PID, LOG_SYSLOG, LOG_USER, LOG_UUCP, LOG_WARNING,
|
|
};
|
|
|
|
#[cfg(not(target_os = "redox"))]
|
|
#[pyattr]
|
|
use host_syslog::{LOG_AUTHPRIV, LOG_CRON, LOG_PERROR};
|
|
|
|
#[cfg(target_vendor = "apple")]
|
|
#[pyattr]
|
|
use host_syslog::{LOG_FTP, LOG_INSTALL, LOG_LAUNCHD, LOG_NETINFO, LOG_RAS, LOG_REMOTEAUTH};
|
|
|
|
fn ident_to_utf8_cstring(
|
|
ident: &Py<PyStr>,
|
|
vm: &VirtualMachine,
|
|
) -> PyResult<alloc::ffi::CString> {
|
|
let utf8 = ident.to_str().ok_or_else(|| {
|
|
let start = ident
|
|
.as_wtf8()
|
|
.code_points()
|
|
.position(|c| c.to_char().is_none())
|
|
.unwrap_or(0);
|
|
vm.new_unicode_encode_error(
|
|
vm.ctx.new_str("utf-8"),
|
|
ident.to_owned(),
|
|
start,
|
|
start + 1,
|
|
vm.ctx.new_str("surrogates not allowed"),
|
|
)
|
|
})?;
|
|
alloc::ffi::CString::new(utf8).map_err(|err| err.to_pyexception(vm))
|
|
}
|
|
|
|
fn get_argv(vm: &VirtualMachine) -> Option<PyStrRef> {
|
|
if let Some(argv) = vm.state.config.settings.argv.first()
|
|
&& !argv.is_empty()
|
|
{
|
|
return Some(
|
|
PyStr::from(match argv.find('\\') {
|
|
Some(value) => &argv[value..],
|
|
None => argv,
|
|
})
|
|
.into_ref(&vm.ctx),
|
|
);
|
|
}
|
|
None
|
|
}
|
|
|
|
#[derive(Default, FromArgs)]
|
|
struct OpenLogArgs {
|
|
#[pyarg(any, optional)]
|
|
ident: Option<PyStrRef>,
|
|
#[pyarg(any, default)]
|
|
logoption: i32,
|
|
#[pyarg(any, default = ::LOG_USER)]
|
|
facility: i32,
|
|
}
|
|
|
|
#[pyfunction]
|
|
fn openlog(args: OpenLogArgs, vm: &VirtualMachine) -> PyResult<()> {
|
|
if !vm.state.is_main_interpreter() {
|
|
return Err(vm.new_runtime_error("subinterpreter can't use syslog.openlog()"));
|
|
}
|
|
let logoption = args.logoption;
|
|
let facility = args.facility;
|
|
let ident = match args.ident.clone() {
|
|
Some(ident) => Some(ident_to_utf8_cstring(&ident, vm)?),
|
|
None => get_argv(vm)
|
|
.map(|argv| ident_to_utf8_cstring(&argv, vm))
|
|
.transpose()?,
|
|
}
|
|
.map(|ident| ident.into_boxed_c_str());
|
|
|
|
vm.audit("syslog.openlog", || {
|
|
let audit_ident: PyObjectRef = args.ident.map_or_else(
|
|
|| get_argv(vm).map_or_else(|| vm.ctx.none(), Into::into),
|
|
Into::into,
|
|
);
|
|
(audit_ident, logoption, facility)
|
|
})?;
|
|
|
|
host_syslog::openlog(ident, logoption, facility);
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(FromArgs)]
|
|
struct SysLogArgs {
|
|
#[pyarg(positional)]
|
|
priority: PyObjectRef,
|
|
#[pyarg(positional, optional)]
|
|
message: Option<PyStrRef>,
|
|
}
|
|
|
|
#[pyfunction]
|
|
fn syslog(args: SysLogArgs, vm: &VirtualMachine) -> PyResult<()> {
|
|
let (priority, msg) = match args.message {
|
|
Some(s) => (args.priority.try_into_value(vm)?, s),
|
|
None => (LOG_INFO, args.priority.try_into_value(vm)?),
|
|
};
|
|
|
|
vm.audit("syslog.syslog", || (priority, msg.clone()))?;
|
|
|
|
if !host_syslog::is_open() {
|
|
if !vm.state.is_main_interpreter() {
|
|
return Err(vm.new_runtime_error(
|
|
"subinterpreter can't use syslog.syslog() until the syslog is opened by the main interpreter",
|
|
));
|
|
}
|
|
openlog(
|
|
OpenLogArgs {
|
|
facility: LOG_USER,
|
|
..OpenLogArgs::default()
|
|
},
|
|
vm,
|
|
)?;
|
|
}
|
|
|
|
let cmsg = msg.to_cstring(vm)?;
|
|
host_syslog::syslog(priority, cmsg.as_c_str());
|
|
Ok(())
|
|
}
|
|
|
|
#[pyfunction]
|
|
fn closelog(vm: &VirtualMachine) -> PyResult<()> {
|
|
if !vm.state.is_main_interpreter() {
|
|
return Err(vm.new_runtime_error("subinterpreter can't use syslog.closelog()"));
|
|
}
|
|
vm.audit("syslog.closelog", || ())?;
|
|
|
|
host_syslog::closelog();
|
|
Ok(())
|
|
}
|
|
|
|
#[pyfunction]
|
|
fn setlogmask(maskpri: i32, vm: &VirtualMachine) -> PyResult<i32> {
|
|
vm.audit("syslog.setlogmask", || (maskpri,))?;
|
|
|
|
Ok(host_syslog::setlogmask(maskpri))
|
|
}
|
|
|
|
#[inline]
|
|
#[pyfunction(name = "LOG_MASK")]
|
|
const fn log_mask(pri: i32) -> i32 {
|
|
host_syslog::log_mask(pri)
|
|
}
|
|
|
|
#[inline]
|
|
#[pyfunction(name = "LOG_UPTO")]
|
|
const fn log_upto(pri: i32) -> i32 {
|
|
host_syslog::log_upto(pri)
|
|
}
|
|
}
|