{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/1236","labels_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1236/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1236/comments","events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1236/events","html_url":"https://github.com/rust-lang/rfcs/pull/1236","id":99015974,"number":1236,"title":"RFC: Stabilize catch_panic","user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?v=3","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rfcs/labels/final-comment-period","name":"final-comment-period","color":"207de5"},{"url":"https://api.github.com/repos/rust-lang/rfcs/labels/T-libs","name":"T-libs","color":"bfd4f2"}],"state":"closed","locked":false,"assignee":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?v=3","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"milestone":null,"comments":136,"created_at":"2015-08-04T17:13:21Z","updated_at":"2016-01-08T07:48:47Z","closed_at":"2015-08-31T15:47:24Z","pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1236","html_url":"https://github.com/rust-lang/rfcs/pull/1236","diff_url":"https://github.com/rust-lang/rfcs/pull/1236.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/1236.patch"},"body":"Stabilize `std::thread::catch_panic` after removing the `Send` and `'static` bounds from the closure parameter. \r\n\r\n[Rendered](https://github.com/alexcrichton/rfcs/blob/stabilize-catch-panic/text/0000-stabilize-catch-panic.md)"},"comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments/169921499","html_url":"https://github.com/rust-lang/rfcs/pull/1236#issuecomment-169921499","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1236","id":169921499,"user":{"login":"jamwt","id":61509,"avatar_url":"https://avatars.githubusercontent.com/u/61509?v=3","gravatar_id":"","url":"https://api.github.com/users/jamwt","html_url":"https://github.com/jamwt","followers_url":"https://api.github.com/users/jamwt/followers","following_url":"https://api.github.com/users/jamwt/following{/other_user}","gists_url":"https://api.github.com/users/jamwt/gists{/gist_id}","starred_url":"https://api.github.com/users/jamwt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamwt/subscriptions","organizations_url":"https://api.github.com/users/jamwt/orgs","repos_url":"https://api.github.com/users/jamwt/repos","events_url":"https://api.github.com/users/jamwt/events{/privacy}","received_events_url":"https://api.github.com/users/jamwt/received_events","type":"User","site_admin":false},"created_at":"2016-01-08T07:48:47Z","updated_at":"2016-01-08T07:48:47Z","body":"I'm in the school of thought that Rust has one way of handling recoverable errors--`Result`.  Panic should be like `assert()` in C--something terrible has happened, abandon all hope.  An invariant.  At work we use the `panic2abort` crate to ensure this, and it helps us sleep at night.  As one data point, our Rust daemons have many weeks of uptime serving many billions of requests (as of course do various C daemons that use assert/abort and golang daemons that use panic), so it doesn't seem particularly daunting to achieve reliability using this approach.\r\n\r\nThere are two principal reasons why I'd prefer we not make it easier or more idiomatic to catch panics:\r\n\r\n 1. IME, writing RAII/dtor type code that unfailingly doesn't leak resources, always abort the database transaction, releases the flock etc in the face of unwinding is basically unsolvable-hard.  Those types of issues are seldom examined rigorously and almost never exhaustively tested because there are so many implied code paths. Programmers just don't get it right, particularly when it's not the primary method of error propagation (vs. Result). Furthermore, often some other invariant ends up violated in the destructor (due to earlier execution than expected), and then you abort anyway, but sort of mask the \"real\" issue.  Given this, in practice (in the kind of applications I manage, at least) crashing on the initial problem is *far* preferable to nondeterministic transactional behavior.  It crashes loudly, the daemon restarts in a clean state, drops its fds and sockets and mmaps and later on the devs shuffle on by and fix the bug.  The punishment fits the crime.\r\n\r\n 2. `Result` and friends are so much better of a way to handle failure that I'm scared of encouraging exception-type behavior as yet-another recoverable error path for new rust developers used to exceptions.\r\n\r\nRAII plus destructors plus lexical-scope drop is just awesomely powerful to use so long as it's easy to determine when your destructors run.  Rust is sooo close to giving you exactly what you expect that it's a shame there's this odd corner where what it can give you is rather complicated to reason about.\r\n\r\n**FFI Counterargument**\r\n\r\nI'm going to cheaply lean on the C defense here--C libraries have plenty of abort() type invariants in practice.  To say they're widely used is obviously an understatement.  Yes, unwinding is indeed terrible if you have non-rust frames in your stack.  Abort instead!\r\n\r\nResponding to the \"but you could recover..\"  or \"if you're in e.g. a desktop app, don't punish the user..\"  Do you *really* know for sure nothing has gone wrong when you unwound? Maybe you'll try again and that transaction that didn't unwind correctly will deadlock you.\r\n\r\n**Basically...**\r\n\r\nI'm not totally against catching panics because Rust is all about power and if you Know What You're Doing, by all means...  If you're convinced it's the right call for your use case and you're pretty darn sure everything that needed to be undone was.  Maybe Servo is one of those codebases, for example.  Everyone hates browsers crashing, and the I imagine the Servo devs have a shot at getting early drop pervasively right.\r\n\r\nBut:\r\n\r\n 1. Make it difficult to use, to be frank.  Make it clear it's dangerous.  Going as far as `unsafe` seems appropriate to me, if not in a letter-of-the-law way, then certainly a spirit-of-the-law one.\r\n 2. Make it really easy to get `panic2abort` behavior, and continue to encourage the idea that any panic should be an irrecoverable the-sky-is-falling type event."}}