-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
make ccall sigatomic (defer SIGINT handling) #2622
Comments
see also #1468 |
In code that repeatedly calls Cairo, I've also seen issues with Ctrl-C. |
Making Moreover, Julia's JIT compiler need not generate the sigatomic checks at all unless (One of the comparisons could be eliminated in typical calls by changing the conditional from |
I'm labelling this a bug, since crashing generic C code after |
This is reasonable. Unfortunately (as in #1468) we'd also like to be able to interrupt things like large matrix multiplies, but there doesn't seem to be much we can do about that on our end. |
… non-interruptable ccalls (see also issue JuliaLang#2622)
@JeffBezanson in #5399:
It would be nice to measure the impact. How about adding a Alternatively, |
This seems like the better approach to me if we're going to do this since we would want to default to safe and most cases where someone is calling out to C are not really that performance critical. |
I also think safe-by-default suits Julia well. If we do not have other behavior to group together with interruptable ccalls in a |
I just don't think asynch interrupt is that important. Plus, you might want to break out of a long-running C routine. This doesn't warrant a We are already doing delayed binding of ccalls by checking a cached function pointer for NULL. This would add yet another thing. |
There's no point in allowing people to break out of long-running C routines if doing so has a high probability of creating crashes later; I doubt that most long-running C code is interrupt-safe. I find it hard to believe that the overhead will be anything but negligible except for a very small number of extremely trivial C routines, and decorating these with |
(I would tend to call it |
Creating a branch which adds I won't have time to try this for at least a few days, so if anyone is up to the task, I'm eager to hear about it... |
(And I agree that |
And then I think there is a question of whether it will even work --- I doubt everything in our runtime system and libraries will be completely interrupt-safe. Technically after an async signal the process may be in an undefined state, no matter what you do. A lot of important native routines are very tiny, for example I would prefer almost anything to having to go around and write |
Testing a wrapped ccall with these changes: https://github.com/amitmurthy/julia/compare/amitm;sigatomic?expand=1 I get the following results (extreme case of just trying to detect overhead of sigatomic calls...) On master:
with wrapped ccall:
I think we should just make every ccall (and any other similar functions) atomic by default. Even a compiler switch may not be required. Seg faults simply leave a bad taste in the mouth..... |
If I'm reading your patch correctly, I don't think this has any effect since the |
Right. Should have realized from the "emit" names... Just tested again by just ccall'ing the jl_sigatomic* functions before and after the ccall for sqrt in math.jl and I am getting only slightly increased timings....
Patch - https://github.com/amitmurthy/julia/compare/amitm;sigatomic?expand=1 This should have a runtime effect, right? |
Don't benchmark anonymous functions. Write a foo!(X) function using an explicit loop. Though honestly I don't see the point. The number of C functions as small as sqrt seems quite small, so I find it hard to believe that we'd use interrupt able_ccall in more than a dozen or so places. |
At least use |
For
it is 1.06 seconds for the safe version and 0.59 seconds for the current version. Maybe the difference will be even smaller when emit_ccall itself generates sigatmic* code? In practical terms, @stevengj is right, we may as well just make ccall resilient to interrupts by default.... |
I can see Jeffs point very well. Julia is in an outstanding position where the ffi has almost zero overhead as the overhead is jited away. In all other languages I have seen, there is some overhead which prevents calling scalar C functions in tight loops. This usually leads to recommendation to use the ffi only for vector operations, where the overhead is negligible. |
@amitmurthy, the difference will certainly be smaller when the sigatomic is inlined; it is much more expensive to do a subroutine call than a comparison. @tknopp, the problem with this argument is that very very few C functions as simple as |
What typically happens is somebody says "To try out julia, I compared a simple loop (c)calling sqrt in C++ and Julia, and Julia was 50% slower. Why is Julia so much slower for something so simple?" The C++ program, of course, just dies entirely on ^C, but that is not going to occur to anybody as a point of comparison. From my perspective, we work very hard to generate good code, so it is disheartening when more stuff has to be crammed into the pipeline. Often each extra "thing" is 2%, but over time there are 20 of those things. But, @stevengj is right that the overhead will be much less with the sigatomic stuff inlined, and in the specific case of sqrt we should be inlining it. |
@JeffBezanson, we already get tons of I did [something naive] and Julia was X times slower than Y comments. Slowing down the extremely unusual case of calling your own trivial C function in a tight loop (as opposed to something like |
Ok, I think the way I want to handle this is to make ccall sigatomic by default, and have a compiler switch to control it. My reasoning is that whether you need ^C depends on whether you are working interactively, which is a fairly global property. When we reach the point of statically compiling whole programs, it makes sense to ask to strip out all sigatomic stuff. |
@JeffBezanson, why do you need a compiler switch? Just turn off the sigatomic |
@JeffBezanson is there a way to completely remove signal handling (other than the Because MATLAB runs on the JVM, if a library installs it's own signal handler then complications can cause MATLAB to crash. |
(Note that the |
How do the LLVM intrinsics work? Do they end up calling the system libm, or does LLVM have fast implementations? We have @simonbyrne 's |
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
* Remove unnecessary sigatomic * Make flisp calls sigatomic * Make type inference calls sigatomic * Refactor interthread communication through signal * Make sure `sleep` is aborted on `SIGINT` on Linux to deliver the exception faster * Implement force signal throwing when `SIGINT` arrives too frequently * Hack to abort io syscall on `SIGINT` Fix #1468; Fix #2622; Towards #14675
Hooray! |
Currently, a ctrl-c in the REPL can interrupt a
ccall
to an external library, leaving that library in an inconsistent state and producing crashes or other problems later (see e.g. PyCall issue #15).Julia's C API (
julia.h
) hasSIGATOMIC
macros to protect critical code regions from being interrupted by ctrl-c (SIGINT
), but these are not easily accessible from Julia.Arguably, every
ccall
should be made sigatomic by default, on the theory that C code in general is not interrupt-safe (with a separateinterruptable_ccall
for cases that are known to be re-entrant and interrupt-safe). Note that Python does the same thing. As noted below, the performance penalty for this is almost certainly negligible under ordinary circumstances.The text was updated successfully, but these errors were encountered: