Skip to content

Commit dd79e16

Browse files
committed
small changes from review
1 parent d420f85 commit dd79e16

File tree

7 files changed

+26
-17
lines changed

7 files changed

+26
-17
lines changed

src/shims/tls.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
244244
this.eval_windows("thread_local_key", "p_thread_callback")?.to_pointer(this)?;
245245
let thread_callback = this.get_ptr_fn(thread_callback)?.as_instance()?;
246246

247-
// Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits but std treats both the same.
247+
// FIXME: Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits
248+
// but std treats both the same.
248249
let reason = this.eval_windows("c", "DLL_THREAD_DETACH")?;
249250

250251
// The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`.
251-
// `h` should be a handle to the current module and what `pv` should be is unknown
252+
// FIXME: `h` should be a handle to the current module and what `pv` should be is unknown
252253
// but both are ignored by std
253254
this.call_function(
254255
thread_callback,

src/shims/unix/thread.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5252
let this = self.eval_context_mut();
5353

5454
let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
55-
this.detach_thread(thread_id.try_into().expect("thread ID should fit in u32"), false)?;
55+
this.detach_thread(
56+
thread_id.try_into().expect("thread ID should fit in u32"),
57+
/*allow_terminated_joined*/ false,
58+
)?;
5659

5760
Ok(0)
5861
}

src/shims/windows/foreign_items.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
355355
let [handle, timeout] =
356356
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
357357

358-
this.WaitForSingleObject(handle, timeout)?;
359-
360-
this.write_scalar(Scalar::from_u32(0), dest)?;
358+
let ret = this.WaitForSingleObject(handle, timeout)?;
359+
this.write_scalar(Scalar::from_u32(ret), dest)?;
361360
}
362361
"GetCurrentThread" => {
363362
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;

src/shims/windows/handle.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
157157
let handle = this.read_scalar(handle_op)?.check_init()?;
158158

159159
match Handle::from_scalar(handle, this)? {
160-
Some(Handle::Thread(thread)) => this.detach_thread(thread, true)?,
160+
Some(Handle::Thread(thread)) =>
161+
this.detach_thread(thread, /*allow_terminated_joined*/ true)?,
161162
_ => this.invalid_handle("CloseHandle")?,
162163
}
163164

src/shims/windows/thread.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2222
let security = this.read_pointer(security_op)?;
2323

2424
// stacksize is ignored, but still needs to be a valid usize
25-
let _ = this.read_scalar(stacksize_op)?.to_machine_usize(this)?;
25+
this.read_scalar(stacksize_op)?.to_machine_usize(this)?;
2626

2727
let start_routine = this.read_pointer(start_op)?;
2828

@@ -40,6 +40,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4040
let stack_size_param_is_a_reservation =
4141
this.eval_windows("c", "STACK_SIZE_PARAM_IS_A_RESERVATION")?.to_u32()?;
4242

43+
// we ignore the `STACK_SIZE_PARAM_IS_A_RESERVATION` flag
44+
// reserved stack memory cannot be observed by the program
4345
if flags != 0 && flags != stack_size_param_is_a_reservation {
4446
throw_unsup_format!("unsupported `dwCreationFlags` {} in `CreateThread`", flags)
4547
}
@@ -61,7 +63,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6163
&mut self,
6264
handle_op: &OpTy<'tcx, Provenance>,
6365
timeout_op: &OpTy<'tcx, Provenance>,
64-
) -> InterpResult<'tcx> {
66+
) -> InterpResult<'tcx, u32> {
6567
let this = self.eval_context_mut();
6668

6769
let handle = this.read_scalar(handle_op)?.check_init()?;
@@ -70,8 +72,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7072

7173
let thread = match Handle::from_scalar(handle, this)? {
7274
Some(Handle::Thread(thread)) => thread,
73-
// Unlike on posix, joining the current thread is not UB on windows.
74-
// It will just deadlock.
75+
// Unlike on posix, the outcome of joining the current thread is not documented.
76+
// On current Windows, it just deadlocks.
7577
Some(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.get_active_thread(),
7678
_ => this.invalid_handle("WaitForSingleObject")?,
7779
};
@@ -82,6 +84,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
8284

8385
this.join_thread(thread)?;
8486

85-
Ok(())
87+
Ok(0)
8688
}
8789
}

src/thread.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
181181
}
182182

183183
/// A specific moment in time.
184-
#[derive(Debug, Copy, Clone)]
184+
#[derive(Debug)]
185185
pub enum Time {
186186
Monotonic(Instant),
187187
RealTime(SystemTime),
@@ -357,16 +357,19 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
357357
///
358358
/// `allow_terminated_joined` allows detaching joined threads that have already terminated.
359359
/// This matches Windows's behavior for `CloseHandle`.
360+
///
361+
/// See https://docs.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers:
362+
/// > The handle is valid until closed, even after the thread it represents has been terminated.
360363
fn detach_thread(&mut self, id: ThreadId, allow_terminated_joined: bool) -> InterpResult<'tcx> {
361364
trace!("detaching {:?}", id);
362365

363366
let is_ub = if allow_terminated_joined && self.threads[id].state == ThreadState::Terminated
364367
{
368+
// "Detached" in particular means "not yet joined". Redundant detaching is still UB.
365369
self.threads[id].join_status == ThreadJoinStatus::Detached
366370
} else {
367371
self.threads[id].join_status != ThreadJoinStatus::Joinable
368372
};
369-
370373
if is_ub {
371374
throw_ub_format!("trying to detach thread that was already detached or joined");
372375
}
@@ -406,7 +409,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
406409
}
407410

408411
/// Mark that the active thread tries to exclusively join the thread with `joined_thread_id`.
409-
/// If the thread is already joined by another thread
412+
/// If the thread is already joined by another thread, it will throw UB
410413
fn join_thread_exclusive(
411414
&mut self,
412415
joined_thread_id: ThreadId,
@@ -424,7 +427,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
424427
self.threads
425428
.iter()
426429
.all(|thread| thread.state != ThreadState::BlockedOnJoin(joined_thread_id)),
427-
"a joinable thread already has threads waiting for its termination"
430+
"this thread already has threads waiting for its termination"
428431
);
429432

430433
self.join_thread(joined_thread_id, data_race)

tests/fail/concurrency/windows_join_main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extern "system" {
1212

1313
const INFINITE: u32 = u32::MAX;
1414

15-
// This is how miri represents the handle for thread 0.
15+
// XXX HACK: This is how miri represents the handle for thread 0.
1616
// This value can be "legitimately" obtained by using `GetCurrentThread` with `DuplicateHandle`
1717
// but miri does not implement `DuplicateHandle` yet.
1818
const MAIN_THREAD: isize = (2i32 << 30) as isize;

0 commit comments

Comments
 (0)