starlark/util/rtabort.rs
1/*
2 * Copyright 2018 The Starlark in Rust Authors.
3 * Copyright (c) Facebook, Inc. and its affiliates.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18use std::fmt::Arguments;
19use std::io;
20use std::process;
21
22/// Like `panic!`, but aborts the process instead of unwinding.
23///
24/// Although we compile buck2 with `panic=abort`, this is safer because
25/// others may copy-paste code.
26macro_rules! rtabort {
27 ($m:literal) => {
28 $crate::util::rtabort::rtabort_impl_fixed_string(
29 file!(),
30 line!(),
31 $m,
32 )
33 };
34 ($($t:tt)*) => {
35 $crate::util::rtabort::rtabort_impl(
36 file!(),
37 line!(),
38 format_args!($($t)*),
39 )
40 };
41}
42
43pub(crate) use rtabort;
44
45#[cold]
46pub(crate) fn rtabort_impl_fixed_string(file: &str, line: u32, message: &str) -> ! {
47 rtabort_impl(file, line, format_args!("{}", message));
48}
49
50#[cold]
51pub(crate) fn rtabort_impl(file: &str, line: u32, msg: Arguments) -> ! {
52 // Make sure we abort even if formatting panics.
53 let _abort = AbortOnDrop;
54
55 // `eprintln!` followed by `abort` does not print anything in tests.
56 io::Write::write_fmt(
57 &mut io::stderr(),
58 format_args!("{}:{}: abort: {}\n", file, line, msg),
59 )
60 .ok();
61
62 // Tell the compiler that we never return.
63 process::abort();
64}
65
66struct AbortOnDrop;
67
68impl Drop for AbortOnDrop {
69 fn drop(&mut self) {
70 process::abort();
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 fn _test_compiles_fixed_string() {
77 rtabort!("test");
78 }
79
80 fn _test_compiles_with_format_args() {
81 rtabort!("test {}", 17);
82 }
83
84 #[test]
85 fn test_rtabort() {
86 // Uncomment to test.
87 // rtabort!("test {}", 17);
88 // rtabort!("test {}", { panic!(); 17 });
89 }
90}