Skip to content

Commit 2532b86

Browse files
committed
Propagate the return code from the start lang item
Fixes #1064 This ensures that we set the error code properly when a panic unwinds past `main`. I'm not sure what the best way to write a test for this is
1 parent e588d95 commit 2532b86

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/eval.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syntax::source_map::DUMMY_SP;
1111
use crate::{
1212
EnvVars, Evaluator, FnVal, HelpersEvalContextExt, InterpCx, InterpError,
1313
InterpResult, MemoryExtra, MiriMemoryKind, Pointer, Scalar, StackPopCleanup, Tag,
14-
TlsEvalContextExt,
14+
TlsEvalContextExt, MPlaceTy
1515
};
1616

1717
/// Configuration needed to spawn a Miri instance.
@@ -34,7 +34,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
3434
tcx: TyCtxt<'tcx>,
3535
main_id: DefId,
3636
config: MiriConfig,
37-
) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, Evaluator<'tcx>>> {
37+
) -> InterpResult<'tcx, (InterpCx<'mir, 'tcx, Evaluator<'tcx>>, MPlaceTy<'tcx, Tag>)> {
3838
let mut ecx = InterpCx::new(
3939
tcx.at(syntax::source_map::DUMMY_SP),
4040
ty::ParamEnv::reveal_all(),
@@ -170,27 +170,31 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
170170
ecx.write_scalar(Scalar::from_u32(0), errno_place.into())?;
171171
ecx.machine.last_error = Some(errno_place);
172172

173-
Ok(ecx)
173+
Ok((ecx, ret_ptr))
174174
}
175175

176176
pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) {
177-
let mut ecx = match create_ecx(tcx, main_id, config) {
178-
Ok(ecx) => ecx,
177+
let (mut ecx, ret_ptr) = match create_ecx(tcx, main_id, config) {
178+
Ok(v) => v,
179179
Err(mut err) => {
180180
err.print_backtrace();
181181
panic!("Miri initialziation error: {}", err.kind)
182182
}
183183
};
184184

185185
// Perform the main execution.
186-
let res: InterpResult<'_> = (|| {
186+
let res: InterpResult<'_, i64> = (|| {
187187
ecx.run()?;
188-
ecx.run_tls_dtors()
188+
// Read the return code pointer *before* we run TLS destructors, to assert
189+
// that it was written to by the time that `start` lang item returned.
190+
let return_code = ecx.read_scalar(ret_ptr.into())?.not_undef()?.to_machine_isize(&ecx)?;
191+
ecx.run_tls_dtors()?;
192+
Ok(return_code)
189193
})();
190194

191195
// Process the result.
192196
match res {
193-
Ok(()) => {
197+
Ok(return_code) => {
194198
let leaks = ecx.memory.leak_report();
195199
// Disable the leak test on some platforms where we do not
196200
// correctly implement TLS destructors.
@@ -199,6 +203,7 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) {
199203
if !ignore_leaks && leaks != 0 {
200204
tcx.sess.err("the evaluated program leaked memory");
201205
}
206+
std::process::exit(return_code as i32);
202207
}
203208
Err(mut e) => {
204209
// Special treatment for some error kinds

0 commit comments

Comments
 (0)