Merge branch 'patch5' into 'master'
feat: rwlock Closes #196 See merge request redox-os/relibc!594
This commit is contained in:
@@ -114,7 +114,7 @@ pub unsafe extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -
|
||||
0
|
||||
}
|
||||
|
||||
pub(crate) type RlctRwlock = crate::sync::rwlock::Rwlock;
|
||||
pub(crate) type RlctRwlock = crate::sync::rwlock::InnerRwLock;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub(crate) struct RlctRwlockAttr {
|
||||
|
||||
@@ -297,7 +297,7 @@ pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn drand48() -> c_double {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
*xsubi = params.step(*xsubi);
|
||||
xsubi.get_f64()
|
||||
@@ -330,7 +330,7 @@ pub extern "C" fn ecvt(
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn erand48(xsubi: *mut c_ushort) -> c_double {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
|
||||
let new_xsubi_value = params.step(xsubi_mut.into());
|
||||
*xsubi_mut = new_xsubi_value.into();
|
||||
@@ -521,7 +521,7 @@ pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: size_
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
|
||||
let new_xsubi_value = params.step(xsubi_mut.into());
|
||||
*xsubi_mut = new_xsubi_value.into();
|
||||
@@ -586,7 +586,7 @@ pub extern "C" fn labs(i: c_long) -> c_long {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn lcong48(param: *mut c_ushort) {
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
let mut params = rand48::params_lock();
|
||||
let mut params = rand48::params_mut();
|
||||
|
||||
let param_slice = slice::from_raw_parts(param, 7);
|
||||
|
||||
@@ -643,7 +643,7 @@ pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t {
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn lrand48() -> c_long {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
*xsubi = params.step(*xsubi);
|
||||
xsubi.get_u31()
|
||||
@@ -843,7 +843,7 @@ pub unsafe extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mrand48() -> c_long {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
*xsubi = params.step(*xsubi);
|
||||
xsubi.get_i32()
|
||||
@@ -860,7 +860,7 @@ pub extern "C" fn mrand48() -> c_long {
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn nrand48(xsubi: *mut c_ushort) -> c_long {
|
||||
let params = rand48::params_lock();
|
||||
let params = rand48::params();
|
||||
let xsubi_mut: &mut [c_ushort; 3] = slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap();
|
||||
let new_xsubi_value = params.step(xsubi_mut.into());
|
||||
*xsubi_mut = new_xsubi_value.into();
|
||||
@@ -1196,7 +1196,7 @@ pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
|
||||
pub unsafe extern "C" fn seed48(seed16v: *mut c_ushort) -> *mut c_ushort {
|
||||
static mut BUFFER: [c_ushort; 3] = [0; 3];
|
||||
|
||||
let mut params = rand48::params_lock();
|
||||
let mut params = rand48::params_mut();
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
|
||||
let seed16v_ref: &[c_ushort; 3] = slice::from_raw_parts(seed16v, 3).try_into().unwrap();
|
||||
@@ -1296,7 +1296,7 @@ pub unsafe extern "C" fn srand(seed: c_uint) {
|
||||
/// state.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn srand48(seedval: c_long) {
|
||||
let mut params = rand48::params_lock();
|
||||
let mut params = rand48::params_mut();
|
||||
let mut xsubi = rand48::xsubi_lock();
|
||||
|
||||
params.reset();
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
use crate::{
|
||||
platform::types::*,
|
||||
sync::{Mutex, MutexGuard},
|
||||
sync::{
|
||||
rwlock::{self, RwLock},
|
||||
Mutex, MutexGuard,
|
||||
},
|
||||
};
|
||||
|
||||
/// A 48-bit integer, used for the 48-bit arithmetic in these functions.
|
||||
@@ -119,13 +122,19 @@ impl Params {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consider using rwlock instead of mutex for more fine-grained access
|
||||
/// Immediately get the global Params lock, or panic if unsuccessful.
|
||||
pub fn params_lock<'a>() -> MutexGuard<'a, Params> {
|
||||
static PARAMS: Mutex<Params> = Mutex::<Params>::new(Params::new());
|
||||
static PARAMS: RwLock<Params> = RwLock::<Params>::new(Params::new());
|
||||
|
||||
/// Immediately get the global [`Params`] lock for reading, or panic if unsuccessful.
|
||||
pub fn params<'a>() -> rwlock::ReadGuard<'a, Params> {
|
||||
PARAMS
|
||||
.try_lock()
|
||||
.try_read()
|
||||
.expect("unable to acquire LCG parameter lock")
|
||||
}
|
||||
|
||||
/// Immediately get the global [`Params`] lock for writing, or panic if unsuccessful.
|
||||
pub fn params_mut<'a>() -> rwlock::WriteGuard<'a, Params> {
|
||||
PARAMS
|
||||
.try_write()
|
||||
.expect("unable to acquire LCG parameter lock")
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -29,7 +29,7 @@ use crate::{
|
||||
types::{c_char, c_int, c_uint, c_void},
|
||||
Pal, Sys,
|
||||
},
|
||||
sync::Mutex,
|
||||
sync::rwlock::RwLock,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -49,7 +49,7 @@ use super::{
|
||||
// do better errors than just goblin::Error::Malformed
|
||||
|
||||
// TODO: rwlock?
|
||||
static GLOBAL_SCOPE: Mutex<Scope> = Mutex::new(Scope::global());
|
||||
static GLOBAL_SCOPE: RwLock<Scope> = RwLock::new(Scope::global());
|
||||
|
||||
/// Same as [`crate::fs::File`], but does not touch [`crate::platform::ERRNO`] as the dynamic
|
||||
/// linker does not have thread-local storage.
|
||||
@@ -371,7 +371,7 @@ impl Linker {
|
||||
eprintln!("[ld.so]: moving {} into the global scope", obj.name);
|
||||
}
|
||||
|
||||
let mut global_scope = GLOBAL_SCOPE.lock();
|
||||
let mut global_scope = GLOBAL_SCOPE.write();
|
||||
obj.scope.move_into(&mut global_scope);
|
||||
}
|
||||
|
||||
@@ -419,8 +419,8 @@ impl Linker {
|
||||
if let Some(handle) = handle.as_ref() {
|
||||
&handle.as_ref().scope
|
||||
} else {
|
||||
guard = GLOBAL_SCOPE.lock();
|
||||
&*guard
|
||||
guard = GLOBAL_SCOPE.read();
|
||||
&guard
|
||||
}
|
||||
.get_sym(name)
|
||||
.map(|(symbol, _, obj)| {
|
||||
@@ -454,7 +454,7 @@ impl Linker {
|
||||
// objects map.
|
||||
if Arc::strong_count(&obj) == 2 {
|
||||
// Remove from the global scope.
|
||||
match *GLOBAL_SCOPE.lock() {
|
||||
match *GLOBAL_SCOPE.write() {
|
||||
Scope::Global { ref mut objs } => {
|
||||
objs.retain(|o| !Weak::ptr_eq(o, &Arc::downgrade(&obj)));
|
||||
}
|
||||
@@ -713,10 +713,10 @@ impl Linker {
|
||||
if let Some(dependent) = dependent {
|
||||
match scope {
|
||||
ObjectScope::Local => dependent.scope.add(&obj),
|
||||
ObjectScope::Global => GLOBAL_SCOPE.lock().add(&obj),
|
||||
ObjectScope::Global => GLOBAL_SCOPE.write().add(&obj),
|
||||
}
|
||||
} else if let ObjectScope::Global = scope {
|
||||
GLOBAL_SCOPE.lock().add(&obj);
|
||||
GLOBAL_SCOPE.write().add(&obj);
|
||||
}
|
||||
|
||||
objects_data.push(data);
|
||||
@@ -817,7 +817,7 @@ impl Linker {
|
||||
)))?;
|
||||
|
||||
let resolved = GLOBAL_SCOPE
|
||||
.lock()
|
||||
.read()
|
||||
.get_sym(name)
|
||||
.or_else(|| obj.scope.get_sym(name))
|
||||
.map(|(sym, _, _)| sym.as_ptr())
|
||||
@@ -869,7 +869,7 @@ impl Linker {
|
||||
)))?;
|
||||
|
||||
let symbol = GLOBAL_SCOPE
|
||||
.lock()
|
||||
.read()
|
||||
.get_sym(name)
|
||||
.or_else(|| obj.scope.get_sym(name))
|
||||
.map(|(sym, _, obj)| (sym, obj.tls_offset));
|
||||
@@ -1067,7 +1067,7 @@ extern "C" fn __plt_resolve_inner(obj: *const DSO, relocation_index: c_uint) ->
|
||||
)
|
||||
};
|
||||
|
||||
let resolved = resolve_sym(name.to_str().unwrap(), &[&GLOBAL_SCOPE.lock(), &obj.scope])
|
||||
let resolved = resolve_sym(name.to_str().unwrap(), &[&GLOBAL_SCOPE.read(), &obj.scope])
|
||||
.expect(&format!("symbol '{}' not found", name.to_str().unwrap()))
|
||||
.as_ptr();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#![feature(sync_unsafe_cell)]
|
||||
#![feature(thread_local)]
|
||||
#![feature(vec_into_raw_parts)]
|
||||
#![feature(negative_impls)]
|
||||
#![allow(clippy::cast_lossless)]
|
||||
#![allow(clippy::cast_ptr_alignment)]
|
||||
#![allow(clippy::derive_hash_xor_eq)]
|
||||
|
||||
@@ -7,29 +7,6 @@ use syscall::{
|
||||
SetSighandlerData, SIGCONT,
|
||||
};
|
||||
|
||||
use crate::sync::rwlock::Rwlock;
|
||||
|
||||
use redox_rt::{proc::FdGuard, signal::sighandler_function};
|
||||
|
||||
pub use redox_rt::proc::*;
|
||||
|
||||
static CLONE_LOCK: Rwlock = Rwlock::new(crate::pthread::Pshared::Private);
|
||||
|
||||
struct Guard;
|
||||
impl Drop for Guard {
|
||||
fn drop(&mut self) {
|
||||
CLONE_LOCK.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rdlock() -> impl Drop {
|
||||
CLONE_LOCK.acquire_read_lock(None);
|
||||
|
||||
Guard
|
||||
}
|
||||
pub fn wrlock() -> impl Drop {
|
||||
CLONE_LOCK.acquire_write_lock(None);
|
||||
|
||||
Guard
|
||||
}
|
||||
pub use redox_rt::thread::*;
|
||||
pub use redox_rt::{proc::*, thread::*};
|
||||
|
||||
@@ -34,6 +34,7 @@ use crate::{
|
||||
unistd::{F_OK, R_OK, W_OK, X_OK},
|
||||
},
|
||||
io::{self, prelude::*, BufReader},
|
||||
sync::rwlock::RwLock,
|
||||
};
|
||||
|
||||
pub use redox_rt::proc::FdGuard;
|
||||
@@ -75,6 +76,8 @@ macro_rules! path_from_c_str {
|
||||
|
||||
use self::{exec::Executable, path::canonicalize};
|
||||
|
||||
static CLONE_LOCK: RwLock<()> = RwLock::new(());
|
||||
|
||||
/// Redox syscall implementation of the platform abstraction layer.
|
||||
pub struct Sys;
|
||||
|
||||
@@ -260,7 +263,7 @@ impl Pal for Sys {
|
||||
|
||||
unsafe fn fork() -> Result<pid_t> {
|
||||
// TODO: Find way to avoid lock.
|
||||
let _guard = clone::wrlock();
|
||||
let _guard = CLONE_LOCK.write();
|
||||
|
||||
Ok(clone::fork_impl()? as pid_t)
|
||||
}
|
||||
@@ -726,7 +729,7 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
unsafe fn rlct_clone(stack: *mut usize) -> Result<crate::pthread::OsTid> {
|
||||
let _guard = clone::rdlock();
|
||||
let _guard = CLONE_LOCK.read();
|
||||
let res = clone::rlct_clone_impl(stack);
|
||||
|
||||
res.map(|mut fd| crate::pthread::OsTid {
|
||||
|
||||
+140
-3
@@ -1,8 +1,13 @@
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::{
|
||||
cell::UnsafeCell,
|
||||
fmt, ops,
|
||||
ptr::NonNull,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use crate::{header::time::timespec, pthread::Pshared};
|
||||
|
||||
pub struct Rwlock {
|
||||
pub struct InnerRwLock {
|
||||
state: AtomicU32,
|
||||
}
|
||||
// PTHREAD_RWLOCK_INITIALIZER is defined as "all zeroes".
|
||||
@@ -15,7 +20,7 @@ const EXCLUSIVE: u32 = COUNT_MASK;
|
||||
// supporting timeouts.
|
||||
// TODO: Add futex ops that use bitmasks.
|
||||
|
||||
impl Rwlock {
|
||||
impl InnerRwLock {
|
||||
pub const fn new(_pshared: Pshared) -> Self {
|
||||
Self {
|
||||
state: AtomicU32::new(0),
|
||||
@@ -143,3 +148,135 @@ impl Rwlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RwLock<T: ?Sized> {
|
||||
inner: InnerRwLock,
|
||||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized + Send> Send for RwLock<T> {}
|
||||
unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
|
||||
|
||||
impl<T> RwLock<T> {
|
||||
pub const fn new(val: T) -> Self {
|
||||
Self {
|
||||
inner: InnerRwLock::new(Pshared::Private),
|
||||
data: UnsafeCell::new(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> RwLock<T> {
|
||||
pub fn read(&self) -> ReadGuard<'_, T> {
|
||||
self.inner.acquire_read_lock(None);
|
||||
unsafe { ReadGuard::new(self) }
|
||||
}
|
||||
|
||||
pub fn write(&self) -> WriteGuard<'_, T> {
|
||||
self.inner.acquire_write_lock(None);
|
||||
unsafe { WriteGuard::new(self) }
|
||||
}
|
||||
|
||||
pub fn try_read(&self) -> Option<ReadGuard<'_, T>> {
|
||||
if self.inner.try_acquire_read_lock().is_ok() {
|
||||
Some(unsafe { ReadGuard::new(self) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_write(&self) -> Option<WriteGuard<'_, T>> {
|
||||
if self.inner.try_acquire_write_lock().is_ok() {
|
||||
Some(unsafe { WriteGuard::new(self) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReadGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> !Send for ReadGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Sync> Sync for ReadGuard<'_, T> {}
|
||||
|
||||
impl<'a, T: ?Sized> ReadGuard<'a, T> {
|
||||
unsafe fn new(lock: &'a RwLock<T>) -> Self {
|
||||
Self { lock }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::Deref for ReadGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: We have shared reference to the data.
|
||||
unsafe { &*self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Drop for ReadGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.lock.inner.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for ReadGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Display> fmt::Display for ReadGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WriteGuard<'a, T: ?Sized + 'a> {
|
||||
lock: &'a RwLock<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> !Send for WriteGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Sync> Sync for WriteGuard<'_, T> {}
|
||||
|
||||
impl<'a, T: ?Sized> WriteGuard<'a, T> {
|
||||
unsafe fn new(lock: &'a RwLock<T>) -> Self {
|
||||
Self { lock }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::Deref for WriteGuard<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
// SAFETY: We have exclusive reference to the data.
|
||||
unsafe { &*self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> ops::DerefMut for WriteGuard<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
// SAFETY: We have exclusive reference to the data.
|
||||
unsafe { &mut *self.lock.data.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Drop for WriteGuard<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.lock.inner.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for WriteGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + fmt::Display> fmt::Display for WriteGuard<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,5 @@
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
Child exited with status 0
|
||||
|
||||
@@ -1,30 +1,5 @@
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Set regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
----- Pre-syscall -----
|
||||
Wait...
|
||||
Get regs
|
||||
Post-syscall
|
||||
Wait...
|
||||
Child exited with status 0
|
||||
|
||||
+9
-7
@@ -48,17 +48,18 @@ int main() {
|
||||
|
||||
int status;
|
||||
while (true) {
|
||||
puts("----- Pre-syscall -----");
|
||||
// puts("----- Pre-syscall -----");
|
||||
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
UNEXP_IF(ptrace, result, != 0);
|
||||
puts("Wait...");
|
||||
// puts("Wait...");
|
||||
result = waitpid(pid, &status, 0);
|
||||
ERROR_IF(waitpid, result, == -1);
|
||||
if (WIFEXITED(status)) { break; }
|
||||
if (WIFEXITED(status))
|
||||
break;
|
||||
|
||||
struct user_regs_struct regs;
|
||||
puts("Get regs");
|
||||
// puts("Get regs");
|
||||
result = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
|
||||
@@ -69,14 +70,15 @@ int main() {
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
}
|
||||
|
||||
puts("Post-syscall");
|
||||
// puts("Post-syscall");
|
||||
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
UNEXP_IF(ptrace, result, != 0);
|
||||
puts("Wait...");
|
||||
// puts("Wait...");
|
||||
result = waitpid(pid, &status, 0);
|
||||
ERROR_IF(waitpid, result, == -1);
|
||||
if (WIFEXITED(status)) { break; }
|
||||
if (WIFEXITED(status))
|
||||
break;
|
||||
}
|
||||
printf("Child exited with status %d\n", WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user