【发布时间】:2020-09-10 13:50:07
【问题描述】:
当我使用 RwLock 和分叉时,我看到了一些我无法解释的行为。基本上,子进程报告 RwLock 仍被获取,而父进程没有,即使它们都运行相同的代码路径。我的理解是子进程应该收到父进程内存空间的独立副本,包括锁,所以他们应该报告不同的结果是没有意义的。
预期的行为是孩子和父母都报告“互斥锁持有:假”。有趣的是,当使用 Mutex 而不是 RwLock 时,这可以正常工作。
use libc::fork;
use std::error::Error;
use std::sync::RwLock;
fn main() -> Result<(), Box<dyn Error>> {
let lock = RwLock::new(());
let guard = lock.write();
let res = unsafe { fork() };
drop(guard);
match res {
0 => {
let held = lock.try_write().is_err();
println!("CHILD mutex held: {}", held);
}
_child_pid => {
let held = lock.try_write().is_err();
println!("PARENT mutex held: {}", held);
}
}
Ok(())
}
输出:
PARENT mutex held: false
CHILD mutex held: true
【问题讨论】:
-
工作原理是这只是未定义的行为:“如果调用线程未持有读写锁 rwlock,则结果未定义。” pubs.opengroup.org/onlinepubs/9699919799/functions/… 看来即使fork出的进程有一个父级内存的副本,但是锁的状态里面肯定有线程id,导致它行为不端。
-
^ 与这些同步抽象通常构建在操作系统原语 (
std::sync) 之上的事实相结合,这对我来说似乎是一个答案,因此可能会泄露实现细节,尤其是unsafe.
标签: rust multiprocessing locking fork mutex