Skip to content

Commit ef3913a

Browse files
authored
Merge pull request #231 from FenrirWolf/panic_hook_alloc
Remove allocations from the ctru panic hook
2 parents 44e6787 + 394da2f commit ef3913a

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

ctru-rs/src/applets/error.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use crate::services::{apt::Apt, gfx::Gfx};
66

7-
use ctru_sys::errorConf;
7+
use ctru_sys::{errorConf, errorDisp, errorInit};
88

99
/// Configuration struct to set up the Error applet.
1010
#[doc(alias = "errorConf")]
@@ -46,7 +46,7 @@ impl PopUp {
4646
pub fn new(word_wrap: WordWrap) -> Self {
4747
let mut state = Box::<errorConf>::default();
4848

49-
unsafe { ctru_sys::errorInit(state.as_mut(), word_wrap as _, 0) };
49+
unsafe { errorInit(state.as_mut(), word_wrap as _, 0) };
5050

5151
Self { state }
5252
}
@@ -94,9 +94,41 @@ impl PopUp {
9494
}
9595
}
9696

97+
struct ErrorConfWriter<'a> {
98+
error_conf: &'a mut errorConf,
99+
index: usize,
100+
}
101+
102+
impl std::fmt::Write for ErrorConfWriter<'_> {
103+
fn write_str(&mut self, s: &str) -> Result<(), std::fmt::Error> {
104+
let max = self.error_conf.Text.len() - 1;
105+
106+
for code_unit in s.encode_utf16() {
107+
if self.index == max {
108+
self.error_conf.Text[self.index] = 0;
109+
return Err(std::fmt::Error);
110+
} else {
111+
self.error_conf.Text[self.index] = code_unit;
112+
self.index += 1;
113+
}
114+
}
115+
116+
self.error_conf.Text[self.index] = 0;
117+
118+
Ok(())
119+
}
120+
}
121+
97122
pub(crate) fn set_panic_hook(call_old_hook: bool) {
98123
use crate::services::gfx::GFX_ACTIVE;
99-
use std::sync::TryLockError;
124+
use std::fmt::Write;
125+
use std::sync::{Mutex, TryLockError};
126+
127+
static ERROR_CONF: Mutex<errorConf> = unsafe { Mutex::new(std::mem::zeroed()) };
128+
129+
let mut lock = ERROR_CONF.lock().unwrap();
130+
131+
unsafe { errorInit(&mut *lock, WordWrap::Enabled as _, 0) };
100132

101133
let old_hook = std::panic::take_hook();
102134

@@ -108,18 +140,23 @@ pub(crate) fn set_panic_hook(call_old_hook: bool) {
108140
old_hook(panic_info);
109141
}
110142

111-
let thread = std::thread::current();
143+
let mut lock = ERROR_CONF.lock().unwrap();
112144

113-
let name = thread.name().unwrap_or("<unnamed>");
145+
let error_conf = &mut *lock;
146+
147+
let mut writer = ErrorConfWriter {
148+
error_conf,
149+
index: 0,
150+
};
114151

115-
let message = format!("thread '{name}' {panic_info}");
152+
let thread = std::thread::current();
116153

117-
let mut popup = PopUp::new(WordWrap::Enabled);
154+
let name = thread.name().unwrap_or("<unnamed>");
118155

119-
popup.set_text(&message);
156+
let _ = write!(writer, "thread '{name}' {panic_info}");
120157

121158
unsafe {
122-
let _ = popup.launch_unchecked();
159+
errorDisp(error_conf);
123160
}
124161
} else {
125162
old_hook(panic_info);

0 commit comments

Comments
 (0)