-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally display the message in native windows for linux + windows #39
Conversation
Looks like I am rustfmt'ing wrong. Will have to look into it tomorrow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there and thank you very much for this PR!
It's not something I would have thought of as the application area for human-panic
(especially because it was created for CLI applications 😉) but a great application nonetheless.
I've marked a few things in my review I'll want to see changed before I'd feel comfortable merging it though.
One thing I noticed while looking at the linux-x11 window code is that you spend a lot of it trying to split the strings in a good way. I'm wondering if there aren't crates to do this sort of work and what it would take to use them. Even if it means refactoring the rest of human-panic
to use it too.
Cargo.toml
Outdated
|
||
[target.'cfg(target_os = "windows")'.dependencies] | ||
winapi = { version = "0.3", features = ["winuser"] } | ||
|
||
[features] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would absolutely want to make either of these an optional dependency. We can't have CLI applications that run headless depend on X11. Adding a feature called gui
(or something along those lines 🚲 🏚️ ...) will make the feature opt-in which is a much safer option here
README.md
Outdated
|
||
When an error eventually occurs, you probably will want to know about it. So | ||
instead of just providing an error message on the command line, we can create a | ||
call to action for people to submit a report. | ||
instead of just providing an error message on the command line or the GUI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would re-phrase to
"[...] instead of crashing without notice or printing a confusing error message [...]"
Rust does by default print an error message but it's not super helpful. I've been meaning to change the wording here for a while anyways 😉
examples/window.rs
Outdated
version: env!("CARGO_PKG_VERSION").into(), | ||
authors: "ルカス".into(), | ||
homepage: "https://github.com/rust-clique/human-panic/issues".into(), | ||
create_window: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also something I'm noticing: if we have an gui
compile feature we don't need to pass this anymore. The feature becomes an opt-in at the dependency level which is much neater IMO.
src/lib.rs
Outdated
//! | ||
//! When an error eventually occurs, you probably will want to know about it. So | ||
//! instead of just providing an error message on the command line, we can create a | ||
//! call to action for people to submit a report. | ||
//! instead of just providing an error message on the command line or the GUI |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same change as in README
//! | ||
//! ## GUI Applications | ||
//! GUI applications don't have a terminal to output errors to. | ||
//! The errors printed to the terminal can optionally be displayed in a message box window. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are you referring to here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nvm, I thought there had been another change in the README we needed to duplicate in the crate docs.
src/lib.rs
Outdated
@@ -50,6 +56,19 @@ extern crate failure; | |||
extern crate serde_derive; | |||
extern crate termcolor; | |||
|
|||
#[cfg(target_os = "windows")] | |||
#[path = "windows_window.rs"] | |||
pub mod window; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please refactor these modules. There should be a gui
or window
module which contains win.rs
and x11.rs
. Gate the loading of window
(or gui
) via the feature mentioned above, then select win
or x11
based on platform
I really like this conceptually! I think like @spacekookie said having this as a separate struct / module inside this repo would be great! I agree having this be opt-in would probably be preferred. Something I'm not entirely convinced of is adding feature flags just for the gui. I feel it isn't great user experience; changing runtime behavior based on a setting inside |
imo adding extra dependencies for non-GUI people seems undesirable. If we agree on that, then its a matter of how to handle it.
Any others? |
@epage edge cases aside, I don't think that the amount of data that's stored on disk is ever a bottleneck. During compilation unused methods are removed anyway, making the resulting binary only include the code that's used. So unless this is proving to be a tremendous amount of extra data (like >= 1gb extra stored on disk), I don't think we should shape the API around that constraint. But to perhaps find a middleground: what if we have a feature flag that's enabled by default, we can get the best of both worlds? Both a convenient way of choosing which method to use, and a flag to trim any overhead for disk-constrained development environments. |
@yoshuawuyts I don't think that letting a feature flag determine runtime behaviour is a bad thing at all. There are plenty of crates to do this and considering that only a small minority of people will want to use the GUI feature of this crate, making it anything other than opt-in would be irresponsible. (EDIT: That being said, if you feel strongly about not letting feature flags influence runtime behaviour, we can keep the We don't know what application build pipelines exist out there and adding a dependency which is absolutely not installed on headless system runs the risk of breaking a lot of user setups. In my opinion this is important when it comes to keeping this change a minor ( |
Wow, I didn't expect the response to be so positive! :D I've opted to use a gui feature to toggle the window on/off at compile time.
I have put no thought into the naming of the feature, feel free to bikeshed all you want, I dont really care what its called. I've run out of time again for today, I'll have to look into rust-fmt tomorrow. Edit: |
Those changes look good! Although did you know you can make an example depend a feature flag? [[example]]
name = "window"
required-features = ["gui"] This might be less overkill than adding a whole new test (which can't run on CI anyways because it's headless) |
I think this case is similar to #7. My comment here: #7 (comment) You are currently in a panicing program, so running any large amount of code might lead to interesting problems. Anything leading to another panic with abort the program immediately. For example, a panic might crash a thread and the thread owner is set up to handle panics - and abort will interact with that handler. I would recommend forwarding to an external program in all cases. This program could handle automated submission, display of a window, etc, and - that's the best feature - can panic by itself, a condition that human_panic can then handle and log. |
I'm not sure what the issue with the abort is? The issue with an external program is it seems annoying to setup for the devs.
Also would using catch_unwind instead of set_hook avoid this issue? |
Turns out the rustfmt issue was because I did All feedback except skade's feedback has been addressed. |
The issue with abort is that the program immediately quits. No cleanup will happen and no further panic handling will take place, including the handling that the host program has set up. (including potential
You can ship a reference implementation, that can be amended to the developers needs. If - for example - the form and function of your feature doesn't match the developers expectations, they'd have to fork
The rough setup for this is that the crashing program does nothing else but execute the error handling program with a defined set of parameters instead. It only has to be in path.
Using catch_panic has wider implications, it breaks catching assumptions of clients and requires the user to wrap all code paths with it, more specifically, it will not catch panics that are caught before the human_panic handler runs. |
First off, thank you @rukai for wanting to upstream your solution! Sorry for taking a week to write this comment, this totally slipped through the cracks. I'm pretty surprised to see this as a feature for human-panic, to be honest. Not that I disagree with the idea per-se, but GUI programming is usually quite different from CLI apps (what this crate currently targets) and there are way more frameworks and differences between OSs to consider. Another potential issue I can see is that people might expect this crate -- if it were to add OS-specific GUI features -- to also use the OS-specific error reporting. And there are a lot of implementations of that. But all this does right now is to write a log file (whose path is rather cryptic and hard to find by hand). Thus, I agree with @skade that a pluggable interface might be more useful than the current solution. |
What are your thoughts on if I instead submit a PR that checks for an external program in the same directory named something like |
Thinking about this some more, could running an external program result in privilege escalation? i.e. if the program is run in a directory without a helper program, then if a user has write access to the directory the program is in but not the actual program. Then they can create the helper program and then their code will be executed on a panic? Or is write access such a strong requirement that this doesn't matter? |
First off, thanks for all the time put into responding to this PR. Different projects will have different needs for this sort of thing. So I think once a project gets to the point of running external programs, the project is better off building their own panic handler. In case someone stumbles upon this PR and wants to implement a gui panic handler or external handler for their project:
|
This is a 🙋 feature
Description
GUI applications cant display the message on the terminal so I have added a native message box so they can use human-panic.
The x11 implementation is based on the SDL ShowSimpleMessageBox
source code:
https://github.com/spurious/SDL-mirror/blob/master/src/video/x11/SDL_x11messagebox.c
Non-ascii characters aren't working on the linux implementation, no idea whats up with that.
Mac OS is left unimplemented as I don't have access to such a machine.
Enabled by the gui feature
Scope
This may not fit it into the scope of this project, due to:
This feature is something I need, so if this change doesn't fit into this project I will need to maintain a fork.
Checklist
Semver Changes
Major change
Screenshots
Linux (i3 wm)
Windows