-
-
Notifications
You must be signed in to change notification settings - Fork 24
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
Better handling on Cygwin for exceptions that occur during exception handling on an alt stack #83
Conversation
src/cysignals/implementation.c
Outdated
|
||
/* Additional platform-specific implementation code */ | ||
#if defined(__CYGWIN__) && defined(__x86_64__) | ||
#include "implementation_cygwin.h" |
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 find an #include
in the middle of the code bad style. Can you put it near the top of the file?
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 agree, though though the file's contents depends on some inline functions I added above. Without it I get complaints about missing declarations--in that case it might almost be better to add an implementation.h
and move the declarations there.
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.
Without it I get complaints about missing declarations
Just add declarations in the beginning of implementation.c
.
in that case it might almost be better to add an implementation.h
My feeling is that header files are mostly used to define a public API, which is not the case 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.
That's not necessarily true at all--headers are just so that declarations an be shared between compilation units, and doesn't necessarily have anything to do with public APIs. It's not unusual to have headers that are used internally for build purposes, but are never "installed".
src/cysignals/implementation.c
Outdated
|
||
|
||
/* Additional platform-specific implementation code */ | ||
#if defined(__CYGWIN__) && defined(__x86_64__) |
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.
Why defined(__x86_64__)
? Even if you need that, it makes more sense to put that check in implementation_cygwin.h
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.
Yes, I agree--I'll change that.
@@ -0,0 +1,61 @@ | |||
/* Cygwin-specific implementation details */ |
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.
This should be a .c
file instead of .h
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.
That was my original call as well--it was a ".c" file to start with and I had #include "implementation_cygwin.c"
. However, I found out the hard way that in this case re-running setup.py
didn't rebuild implementation.o
, which is annoying. Open to ideas.
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 found out the hard way that in this case re-running setup.py didn't rebuild implementation.o, which is annoying.
That issue is independent of the filename.
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.
You would think, but when I changed the filename that seemed to fix it. Maybe it was something else.
I think that, rather than doing an "include" I'd rather just make this a separate (optional) compilation unit. However, that will require adding a couple header files.
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 think that, rather than doing an "include" I'd rather just make this a separate (optional) compilation unit. However, that will require adding a couple header files.
To me, that is overkill to fix a simple dependency problem. Cython and distutils allow adding arbitrary files as dependencies. I don't recall how that works though.
@@ -107,6 +108,60 @@ static inline void reset_CPU(void) | |||
} | |||
|
|||
|
|||
/* Reset all signal handlers and the signal mask to their defaults. */ | |||
static inline void sig_reset_defaults(void) { |
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.
Given that calls to sig_reset_defaults
and sigdie_for_sig
always appear together, why make them separate functions? They are logically related because I need to reset the signal handlers for the kill
in sigdie
to work.
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.
Okay--I was sort of split on that because sig_reset_defaults
looked like it could be useful on its own as well. But in practice it only ended being used in this one place. Alternatively I could keep sig_reset_defaults
as a separate routine, but place a call to it at the beginning of sigdie
.
src/cysignals/implementation.c
Outdated
@@ -344,6 +364,7 @@ static void setup_alt_stack(void) | |||
ss.ss_size = sizeof(alt_stack); | |||
ss.ss_flags = 0; | |||
if (sigaltstack(&ss, NULL) == -1) {perror("sigaltstack"); exit(1);} | |||
PLATFORM_SETUP_ALT_STACK; |
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 don't like PLATFORM_SETUP_ALT_STACK
.
I would rather write this as
#ifdef __CYGWIN__
cygwin_setup_alt_stack();
#endif
just to be explicit that something is happening here only on Cygwin.
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.
My thinking was in theory other platforms might add something here, but I'm just as happy to do the 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.
Even if multiple platforms need to do something, I would prefer platform-specific #ifdef
s.
It would be interesting to know what happens when you don't call |
No, it won't. Cygwin's behavior here is in line with Linux--if a stack overflow occurs it actually disables any non-default SIGSEGV handler unless we have an alternative stack. |
Going to see if I can get this cleaned up. After re-reading this, it probably does make sense to still have a separate |
when handling an exception occurring during signal handling on an alternate stack as on other systems, this basically just prints an error and exits with an appropriate return code (128 + signal number); it also attempts to print a stack trace but this currently fails on Cygwin, and we can live with that for now
243f275
to
d80adca
Compare
Finally got around to updating this. I think it will be a bit better now. We still need to add CI for Cygwin, and I can do that. For now you'll have to I guess take my word for it that this works. |
I moved the call to |
The |
Oops, I don't think I meant to add that stuff here at all. I think they were just uncommitted changes that I accidentally |
1436f07
to
61c96de
Compare
Ugh. It might be unrelated to this, but now I'm getting a hang when I run |
Nevermind, I think might be user error. However, now I'm getting a new failure:
|
Still user/environment error. But now I'm back to the tests hanging in |
This is weird:
I think some of these makefile rules really need to be cleaned up in general, but it's disconcerting that something about how the makefile is written can actually cause the tests to hang. So I need to keep looking into it. This behavior seems to be deterministic though. |
Alright. After more extensive testing over lunch, it looks like this might not be entirely deterministic after all, and maybe it has nothing to do with the different make targets as my initial testing suggested. So now I just need to find out exactly what test it's hanging on... |
Okay. When it does hang it seems to be happening in |
Anyways, I don't think the hang on this test is related to this issue otherwise. |
Interesting that you get a hang, that indicated that the I would be interested to see the output of this test when cysignals was configured with Does it help if you increase the delay in
|
Note that the |
Reading the cysignals code, it seems that the case of two different signals arriving together isn't really supported well. So if you get a This might be fixable, but it's not completely obvious because there are many race conditions to think about. Even then, the So I should probably change the |
Yes, that's what I was implying in this comment. It's entirely possible for the But anyways this discussion might be better continued elsewhere since it's not actually pertinent to this ticket (it just came up here because I didn't start seeing this failure until I most recently tested this ticket). |
Thanks! |
This is a rough idea for how to fix #77. Actually it seems to work pretty reliably but I admit I haven't fully worked out the implications for continuing to do anything with Cygwin in this environment. It's probably pretty unsafe, but this is still better than the current situation (where the OS just quietly terminates the process, and never even sets the exit code in a way that Cygwin can keep track of).