Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSpecify unwinding #638
Conversation
alexcrichton
reviewed
Jan 21, 2015
| unsafe when used incorrectly) can be used to mark functions as specifically not unwinding. This is | ||
| primarily for performance reasons in cases where the function cannot be inferred to not unwind. The | ||
| primary use case for this attribute is the `oom` function that aborts the process in the case of a | ||
| out-of-memory condition. |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 21, 2015
Member
Out of curiosity, I think I remember hearing that code size benefited from this change, do you have some examples or numbers that this could cite to show the benefits that it reaps?
alexcrichton
reviewed
Jan 21, 2015
| the only thing can reasonably be done if we attempt to unwind into code that likely does not know | ||
| how to handle it. | ||
|
|
||
| ## Edge Cases and Other Miscellany |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 21, 2015
Member
Could this section also include the feature gate for the new attributes?
alexcrichton
reviewed
Jan 21, 2015
| safe to use nested invocations of the `try` function. The first part of the implementation would be | ||
| to improve the unwinding system to allow for nested calls to the try function. | ||
|
|
||
| The `try` function itself doesn't need changing. The current signature is `fn try<F:FnOnce()>(f: F) |
This comment has been minimized.
This comment has been minimized.
alexcrichton
reviewed
Jan 21, 2015
| from non-Rust code. As such, the task ends when control returns to original non-Rust code. | ||
|
|
||
| This extension essentially produces "nested tasks", where the thread is one task, then each transfer | ||
| of control from non-Rust code to Rust code is another. Unwinding out of a task is undefined |
This comment has been minimized.
This comment has been minimized.
alexcrichton
Jan 21, 2015
Member
Another possible use case is for a transition to look like Rust -> C -> Rust where Rust gives a callback to a C function which it then calls. Just to clarify, this means that the callback is itself a "nested task"?
This comment has been minimized.
This comment has been minimized.
Aatch
Jan 21, 2015
Author
Contributor
Yes, basically if you enter Rust code from somewhere that is not Rust code, then that is a new task.
bill-myers
reviewed
Jan 21, 2015
|
|
||
| The `try` function itself doesn't need changing. The current signature is `fn try<F:FnOnce()>(f: F) | ||
| -> Result<(), Box<Any + Send>>`, which provides means for the caller to know if the invocation was | ||
| successful. The function would remain unsafe. |
This comment has been minimized.
This comment has been minimized.
bill-myers
Jan 21, 2015
Isn't it possible to make it safe by adding a Send bound to F, and allowing it to be called at any point? (and accepting that TLS access needs to be transactional)
This comment has been minimized.
This comment has been minimized.
thestinger
Jan 21, 2015
Isn't it possible to make it safe by adding a Send bound to F, and allowing it to be called at any point? (and accepting that TLS access needs to be transactional)
So no fast thread-local storage? Or do you want it to do poisoning too?
This comment has been minimized.
This comment has been minimized.
bill-myers
Jan 22, 2015
I think I didn't explain properly, I meant accepting the fact that if you have a function that does two writes to TLS, it may panic in the middle resulting in only a single write, and that you thus need to have a RAII struct implementing Drop if you want transactional atomicity (a simple "scoped TLS assignment guard" could be provided in the standard library).
It's of course also possible to have other schemes with more overhead but I think reaching any agreement on that would be quite hard.
BTW, this means that TLS APIs must not allow borrowing values, just moving them in/out and swapping.
This comment has been minimized.
This comment has been minimized.
dgrunwald
Jan 26, 2015
Contributor
Let's say I'm writing an FFI binding around an C library that makes use of callbacks. I want my binding to be usable by safe rust code.
Currently, the only way to prevent unwinding through the C code is to abort the process when unwinding out of rust code.
But how would an unsafe recursive try help me? I can't prevent the users of my binding from using TLS. So unless I can get a safe try (with all the changes to TLS that entails), I can't use it in my FFI binding, and have to keep aborting the process.
nrc
assigned
alexcrichton
Jan 22, 2015
This comment has been minimized.
This comment has been minimized.
|
cc me |
This comment has been minimized.
This comment has been minimized.
|
Instead of The semantics of
Because |
This comment has been minimized.
This comment has been minimized.
|
@dgrunwald I think that the In general the semantics of @Aatch could you update this RFC with some of the feedback in this thread? There hasn't been much discussion on this but I think that it may be ready for merging soon. |
This comment has been minimized.
This comment has been minimized.
|
AFAIK the only optimizations that For example, I'd expect that With my I was under the impression that this corresponds to the Example:
When the index 5 is out-of-range, by my |
This comment has been minimized.
This comment has been minimized.
|
Back to the main part of the RFC: catching panics and converting them to error codes. The mechanism suggested by this RFC is unsafe, because catching panics is unsafe in the presence of TLS. Moreover, one cannot easily wrap the mechanism behind a safe API, because reasoning about the safety requires global knowledge about the usage of TLS in the program. In my mind, this makes the |
This comment has been minimized.
This comment has been minimized.
|
@dgrunwald Why would |
This comment has been minimized.
This comment has been minimized.
jmesmon
commented
Feb 8, 2015
|
@carllerche if you can assume a lack of panic, all panics become unreachable markers. And bounds check failures panic. As a result, the compiler is able to assume that all of the bounds checks succeed. As to |
This comment has been minimized.
This comment has been minimized.
This was one of the points you mentioned for |
This comment has been minimized.
This comment has been minimized.
I had hoped that it would be possible to get the unwinding implementation to abort the process when a function is marked in some way in the unwinding tables (or even simpler: if the function is not present in the unwinding tables). Unfortunately it looks like LLVM has no good way to do this, and indeed needs a try/catch block: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2014-May/036960.html |
mzabaluev
referenced this pull request
Feb 13, 2015
Open
Prevent unwinding into the caller from callbacks #22
This comment has been minimized.
This comment has been minimized.
|
ping @alexcrichton |
alexcrichton
referenced this pull request
Apr 19, 2015
Closed
Mark extern functions as nounwind + other unwinding-based improvements #21186
alexcrichton
added
the
T-lang
label
May 27, 2015
This comment has been minimized.
This comment has been minimized.
|
Unassigning myself as I believe this has now moved under the T-lang umbrella |
alexcrichton
removed their assignment
May 28, 2015
aturon
self-assigned this
Jul 16, 2015
This comment has been minimized.
This comment has been minimized.
|
We discussed this RFC today in the language subteam meeting, and decided that it ought to be closed in favor of RFC #1236, which covered roughly the same ground. Thanks @Aatch nonetheless. There are also a few bits in here that may be worth pulling out for a later RFC, such as the annotations for functions that govern whether landing pads are created or not. |
Aatch commentedJan 21, 2015
Specifies behaviour around unwinding. Especially with respect to non-Rust code.
Rendered