Skip to content

Commit a0088d7

Browse files
committed
Allow getpid in isolation mode, add gettid support
In order to support gettid when isolation is enabled and when it is disabled, and satisfy its requirement that: In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)). we define the thread ID to be getpid() + <miri internal thread id>. Since the internal thread id of the main thread is zero, this will satisfy that requirement. However, getpid for now was only supported when isolation was disabled. To support getpid in isolation mode, we return a hardcoded value (1000) and return that instead of the real PID.
1 parent 0b22f0c commit a0088d7

File tree

6 files changed

+60
-7
lines changed

6 files changed

+60
-7
lines changed

src/tools/miri/src/shims/env.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
108108
EnvVars::Windows(vars) => vars.get(name),
109109
}
110110
}
111+
112+
fn get_pid(&self) -> u32 {
113+
let this = self.eval_context_ref();
114+
if this.machine.communicate() { std::process::id() } else { 1000 }
115+
}
111116
}

src/tools/miri/src/shims/unix/env.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
274274
let this = self.eval_context_mut();
275275
this.assert_target_os_is_unix("getpid");
276276

277-
this.check_no_isolation("`getpid`")?;
278-
279277
// The reason we need to do this wacky of a conversion is because
280278
// `libc::getpid` returns an i32, however, `std::process::id()` return an u32.
281279
// So we un-do the conversion that stdlib does and turn it back into an i32.
282280
#[allow(clippy::cast_possible_wrap)]
283-
Ok(std::process::id() as i32)
281+
Ok(this.get_pid() as i32)
282+
}
283+
284+
fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> {
285+
let this = self.eval_context_ref();
286+
this.assert_target_os("linux", "gettid");
287+
288+
let index = this.machine.threads.active_thread().to_u32();
289+
290+
// Compute a TID for this thread, ensuring that the main thread has PID == TID.
291+
let tid = this.get_pid().strict_add(index);
292+
293+
#[allow(clippy::cast_possible_wrap)]
294+
Ok(tid as i32)
284295
}
285296
}

src/tools/miri/src/shims/unix/linux/foreign_items.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9494
)?;
9595
this.write_scalar(res, dest)?;
9696
}
97+
"gettid" => {
98+
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
99+
let result = this.linux_gettid()?;
100+
this.write_scalar(Scalar::from_i32(result), dest)?;
101+
}
97102

98103
// Dynamically invoked syscalls
99104
"syscall" => {

src/tools/miri/src/shims/windows/env.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
200200
fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> {
201201
let this = self.eval_context_mut();
202202
this.assert_target_os("windows", "GetCurrentProcessId");
203-
this.check_no_isolation("`GetCurrentProcessId`")?;
204203

205-
Ok(std::process::id())
204+
Ok(this.get_pid())
206205
}
207206

208207
#[allow(non_snake_case)]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@only-target-linux
2+
//@revisions: with_isolation without_isolation
3+
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
4+
5+
use libc::{getpid, gettid};
6+
use std::thread;
7+
8+
fn main() {
9+
thread::spawn(|| {
10+
// Test that in isolation mode a deterministic value will be returned.
11+
// The value 1001 is not important, we only care that whatever the value
12+
// is, won't change from execution to execution.
13+
#[cfg(with_isolation)]
14+
assert_eq!(unsafe { gettid() }, 1001);
15+
16+
assert_ne!(unsafe { gettid() }, unsafe { getpid() });
17+
});
18+
19+
// Test that the thread ID of the main thread is the same as the process
20+
// ID.
21+
assert_eq!(unsafe { gettid() }, unsafe { getpid() });
22+
}

src/tools/miri/tests/pass/getpid.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
//@compile-flags: -Zmiri-disable-isolation
1+
//@revisions: with_isolation without_isolation
2+
//@[without_isolation] compile-flags: -Zmiri-disable-isolation
23

34
fn getpid() -> u32 {
45
std::process::id()
56
}
67

78
fn main() {
8-
getpid();
9+
let pid = getpid();
10+
11+
std::thread::spawn(move || {
12+
assert_eq!(getpid(), pid);
13+
});
14+
15+
// Test that in isolation mode a deterministic value will be returned.
16+
// The value 1000 is not important, we only care that whatever the value
17+
// is, won't change from execution to execution.
18+
#[cfg(with_isolation)]
19+
assert_eq!(pid, 1000);
920
}

0 commit comments

Comments
 (0)