Skip to content

Commit

Permalink
Refactors RustError to supports passing it as argument (#1017)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Oct 5, 2024
1 parent 5935629 commit 5191975
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 134 deletions.
8 changes: 7 additions & 1 deletion gui/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,16 @@ struct VmmScreen {
* Contains VMM event information.
*/
enum VmmEvent_Tag {
VmmEvent_Error,
VmmEvent_WaitingDebugger,
VmmEvent_Exiting,
VmmEvent_Log,
};

struct VmmEvent_Error_Body {
const struct RustError *reason;
};

struct VmmEvent_WaitingDebugger_Body {
const char *addr;
size_t len;
Expand All @@ -108,6 +113,7 @@ struct VmmEvent_Log_Body {
struct VmmEvent {
enum VmmEvent_Tag tag;
union {
struct VmmEvent_Error_Body error;
struct VmmEvent_WaitingDebugger_Body waiting_debugger;
struct VmmEvent_Exiting_Body exiting;
struct VmmEvent_Log_Body log;
Expand Down Expand Up @@ -182,7 +188,7 @@ struct Vmm *vmm_run(const char *kernel,
const struct VmmScreen *screen,
const struct Profile *profile,
const char *debug,
bool (*event)(const struct VmmEvent*, void*),
void (*event)(const struct VmmEvent*, void*),
void *cx,
struct RustError **err);

Expand Down
67 changes: 41 additions & 26 deletions gui/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ MainWindow::MainWindow(QVulkanInstance *vulkan, QList<VkPhysicalDevice> &&vkDevi
#endif

connect(m_launch, &LaunchSettings::saveClicked, this, &MainWindow::saveProfile);
connect(m_launch, &LaunchSettings::startClicked, this, &MainWindow::startKernel);
connect(m_launch, &LaunchSettings::startClicked, this, &MainWindow::startVmm);

m_main->addWidget(m_launch);

Expand Down Expand Up @@ -213,7 +213,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
event->ignore();

// Ask user to confirm.
if (m_kernel) {
if (m_vmm) {
QMessageBox confirm(this);

confirm.setText("Do you want to exit?");
Expand All @@ -226,7 +226,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
return;
}

m_kernel.free();
m_vmm.free();
}

// Close child windows.
Expand Down Expand Up @@ -341,7 +341,7 @@ void MainWindow::saveProfile(Profile *p)
}
}

void MainWindow::startKernel(const QString &debugAddr)
void MainWindow::startVmm(const QString &debugAddr)
{
// Get full path to kernel binary.
std::string kernel;
Expand Down Expand Up @@ -426,24 +426,24 @@ void MainWindow::startKernel(const QString &debugAddr)
return;
}

m_kernel = std::move(vmm);
m_vmm = std::move(vmm);
m_screen->requestUpdate();
}

void MainWindow::updateScreen()
{
// Do nothing if the kernel is not running.
if (!m_kernel) {
// Do nothing if the VMM is not running.
if (!m_vmm) {
return;
}

// Draw the screen.
Rust<RustError> error;

error = vmm_draw(m_kernel);
error = vmm_draw(m_vmm);

if (error) {
m_kernel.free();
m_vmm.free();

QMessageBox::critical(
this,
Expand All @@ -456,17 +456,26 @@ void MainWindow::updateScreen()
m_screen->requestUpdate();
}

void MainWindow::vmmError(const QString &msg)
{
m_vmm.free();

QMessageBox::critical(this, "Error", msg);

m_main->setCurrentIndex(0);
}

void MainWindow::waitingDebugger(const QString &addr)
{
QMessageBox::information(
this,
"Debug",
QString("The kernel are waiting for a debugger at %1.").arg(addr));
QString("The VMM are waiting for a debugger at %1.").arg(addr));
}

void MainWindow::waitKernelExit(bool success)
{
m_kernel.free();
m_vmm.free();

if (!success) {
QMessageBox::critical(
Expand Down Expand Up @@ -555,32 +564,40 @@ void MainWindow::restoreGeometry()
}
}

bool MainWindow::requireEmulatorStopped()
bool MainWindow::requireVmmStopped()
{
if (m_kernel) {
QMessageBox killPrompt(this);
if (m_vmm) {
QMessageBox prompt(this);

killPrompt.setText("Action requires kernel to be stopped to continue.");
killPrompt.setInformativeText("Do you want to kill the kernel?");
killPrompt.setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes);
killPrompt.setDefaultButton(QMessageBox::Cancel);
killPrompt.setIcon(QMessageBox::Warning);
prompt.setText("Action requires VMM to be stopped to continue.");
prompt.setInformativeText("Do you want to kill the VMM?");
prompt.setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes);
prompt.setDefaultButton(QMessageBox::Cancel);
prompt.setIcon(QMessageBox::Warning);

if (killPrompt.exec() != QMessageBox::Yes) {
return true;
if (prompt.exec() != QMessageBox::Yes) {
return false;
}

m_kernel.free();
m_vmm.free();
}

return false;
return true;
}

bool MainWindow::vmmHandler(const VmmEvent *ev, void *cx)
void MainWindow::vmmHandler(const VmmEvent *ev, void *cx)
{
// This method will be called from non-main thread.
auto w = reinterpret_cast<MainWindow *>(cx);

switch (ev->tag) {
case VmmEvent_Error:
QMetaObject::invokeMethod(
w,
&MainWindow::vmmError,
Qt::QueuedConnection,
QString(error_message(ev->error.reason)));
break;
case VmmEvent_WaitingDebugger:
QMetaObject::invokeMethod(
w,
Expand All @@ -604,6 +621,4 @@ bool MainWindow::vmmHandler(const VmmEvent *ev, void *cx)
QString::fromUtf8(ev->log.data, ev->log.len));
break;
}

return true;
}
9 changes: 5 additions & 4 deletions gui/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,23 @@ private slots:
void reportIssue();
void aboutObliteration();
void saveProfile(Profile *p);
void startKernel(const QString &debugAddr);
void startVmm(const QString &debugAddr);
void updateScreen();
private:
void vmmError(const QString &msg);
void waitingDebugger(const QString &addr);
void waitKernelExit(bool success);
void log(VmmLog type, const QString &msg);
bool loadGame(const QString &gameId);
bool requireEmulatorStopped();
bool requireVmmStopped();

static bool vmmHandler(const VmmEvent *ev, void *cx);
static void vmmHandler(const VmmEvent *ev, void *cx);

QStackedWidget *m_main;
ProfileList *m_profiles;
GameListModel *m_games;
LaunchSettings *m_launch;
Screen *m_screen;
QPointer<LogsViewer> m_logs;
Rust<Vmm> m_kernel; // Destroy first.
Rust<Vmm> m_vmm; // Destroy first.
};
17 changes: 11 additions & 6 deletions gui/src/error/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::error::Error;
use std::ffi::{c_char, CString};
use std::fmt::{Display, Write};
Expand All @@ -18,11 +19,11 @@ pub struct RustError(CString);
impl RustError {
/// # Panics
/// If `msg` contains NUL character.
pub fn new(msg: impl Into<Vec<u8>>) -> *mut Self {
Box::into_raw(Self(CString::new(msg).unwrap()).into())
pub fn new(msg: impl Into<Vec<u8>>) -> Self {
Self(CString::new(msg).unwrap())
}

pub fn with_source(msg: impl Display, src: impl Error) -> *mut Self {
pub fn with_source(msg: impl Display, src: impl Error) -> Self {
let mut msg = format!("{} -> {}", msg, src);
let mut src = src.source();

Expand All @@ -31,10 +32,10 @@ impl RustError {
src = e.source();
}

Box::into_raw(Self(CString::new(msg).unwrap()).into())
Self(CString::new(msg).unwrap())
}

pub fn wrap(src: impl Error) -> *mut Self {
pub fn wrap(src: impl Error) -> Self {
let mut msg = src.to_string();
let mut src = src.source();

Expand All @@ -43,6 +44,10 @@ impl RustError {
src = e.source();
}

Box::into_raw(Self(CString::new(msg).unwrap()).into())
Self(CString::new(msg).unwrap())
}

pub fn into_c(self) -> *mut Self {
Box::into_raw(self.into())
}
}
4 changes: 2 additions & 2 deletions gui/src/param/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub unsafe extern "C" fn param_open(file: *const c_char, error: *mut *mut RustEr
let file = match File::open(CStr::from_ptr(file).to_str().unwrap()) {
Ok(v) => v,
Err(e) => {
*error = RustError::with_source("couldn't open the specified file", e);
*error = RustError::with_source("couldn't open the specified file", e).into_c();
return null_mut();
}
};
Expand All @@ -20,7 +20,7 @@ pub unsafe extern "C" fn param_open(file: *const c_char, error: *mut *mut RustEr
let param = match Param::read(file) {
Ok(v) => v,
Err(e) => {
*error = RustError::with_source("couldn't read the specified file", e);
*error = RustError::with_source("couldn't read the specified file", e).into_c();
return null_mut();
}
};
Expand Down
6 changes: 3 additions & 3 deletions gui/src/pkg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub unsafe extern "C" fn pkg_open(file: *const c_char, error: *mut *mut RustErro
let pkg = match Pkg::open(path.to_str().unwrap()) {
Ok(v) => Box::new(v),
Err(e) => {
*error = RustError::wrap(e);
*error = RustError::wrap(e).into_c();
return null_mut();
}
};
Expand All @@ -30,7 +30,7 @@ pub unsafe extern "C" fn pkg_get_param(pkg: *const Pkg, error: *mut *mut RustErr
let param = match (*pkg).get_param() {
Ok(v) => Box::new(v),
Err(e) => {
*error = RustError::wrap(e);
*error = RustError::wrap(e).into_c();
return null_mut();
}
};
Expand All @@ -56,7 +56,7 @@ pub unsafe extern "C" fn pkg_extract(

match (*pkg).extract(root, progress) {
Ok(_) => null_mut(),
Err(e) => RustError::wrap(e),
Err(e) => RustError::wrap(e).into_c(),
}
}

Expand Down
16 changes: 10 additions & 6 deletions gui/src/profile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub unsafe extern "C" fn profile_load(
let root = match CStr::from_ptr(path).to_str() {
Ok(v) => Path::new(v),
Err(_) => {
*err = RustError::new("the specified path is not UTF-8");
*err = RustError::new("the specified path is not UTF-8").into_c();
return null_mut();
}
};
Expand All @@ -37,7 +37,8 @@ pub unsafe extern "C" fn profile_load(
let file = match File::open(&path) {
Ok(v) => v,
Err(e) => {
*err = RustError::with_source(format_args!("couldn't open {}", path.display()), e);
*err = RustError::with_source(format_args!("couldn't open {}", path.display()), e)
.into_c();
return null_mut();
}
};
Expand All @@ -46,7 +47,8 @@ pub unsafe extern "C" fn profile_load(
let p = match ciborium::from_reader(file) {
Ok(v) => v,
Err(e) => {
*err = RustError::with_source(format_args!("couldn't load {}", path.display()), e);
*err = RustError::with_source(format_args!("couldn't load {}", path.display()), e)
.into_c();
return null_mut();
}
};
Expand Down Expand Up @@ -84,12 +86,12 @@ pub unsafe extern "C" fn profile_save(p: *const Profile, path: *const c_char) ->
// Check if path UTF-8.
let root = match CStr::from_ptr(path).to_str() {
Ok(v) => Path::new(v),
Err(_) => return RustError::new("the specified path is not UTF-8"),
Err(_) => return RustError::new("the specified path is not UTF-8").into_c(),
};

// Create a directory.
if let Err(e) = std::fs::create_dir_all(root) {
return RustError::with_source("couldn't create the specified path", e);
return RustError::with_source("couldn't create the specified path", e).into_c();
}

// Create profile.bin.
Expand All @@ -98,12 +100,14 @@ pub unsafe extern "C" fn profile_save(p: *const Profile, path: *const c_char) ->
Ok(v) => v,
Err(e) => {
return RustError::with_source(format_args!("couldn't create {}", path.display()), e)
.into_c()
}
};

// Write profile.bin.
if let Err(e) = ciborium::into_writer(&*p, file) {
return RustError::with_source(format_args!("couldn't write {}", path.display()), e);
return RustError::with_source(format_args!("couldn't write {}", path.display()), e)
.into_c();
}

null_mut()
Expand Down
7 changes: 2 additions & 5 deletions gui/src/vmm/hw/console/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,14 @@ impl<'a, H: Hypervisor> DeviceContext for Context<'a, H> {

// Trigger event.
let msg = std::mem::take(&mut self.msg);
let status = unsafe {

unsafe {
self.dev.event.invoke(VmmEvent::Log {
ty: ty.into(),
data: msg.as_ptr().cast(),
len: msg.len(),
})
};

if !status {
return Ok(false);
}
} else {
return Err(Box::new(ExecError::UnknownField(off)));
}
Expand Down
Loading

0 comments on commit 5191975

Please sign in to comment.