Skip to content

Exit terminal interface gracefully on signals#10185

Closed
takluyver wants to merge 3 commits into
ipython:masterfrom
takluyver:signal-cleanup
Closed

Exit terminal interface gracefully on signals#10185
takluyver wants to merge 3 commits into
ipython:masterfrom
takluyver:signal-cleanup

Conversation

@takluyver

Copy link
Copy Markdown
Member

Closes gh-9944

This sets signal handlers for SIGTERM and SIGHUP while the prompt_toolkit prompt is active, letting it clean up the terminal before the process exits. When the prompt is not active, we restore the previous signals.

This can't work (as far as I know) if other code has set signal handlers at the C level. I don't think this is likely to come up often, but there's a new config option catch_signals=False which users can set to disable our manipulation of signal handlers.

Closes ipythongh-9944

This sets signal handlers for SIGTERM and SIGHUP while the
prompt_toolkit prompt is active, letting it clean up the terminal before
the process exits. When the prompt is not active, we restore the
previous signals.

This can't work (as far as I know) if other code has set signal handlers
at the C level. I don't think this is likely to come up often, but
there's a new config option catch_signals=False which users can set to
disable our manipulation of signal handlers.
They don't exist on Windows
@takluyver takluyver modified the milestone: 5.2 Jan 19, 2017
@jdemeyer

Copy link
Copy Markdown
Contributor

It would be nice if this would also close IPython gracefully:

In [1]: import os; f = open(os.devnull); os.dup2(f.fileno(), 0)

With this branch, this code goes into an infinite loop.

@jdemeyer

Copy link
Copy Markdown
Contributor

Instead of trying to save and restore signals (which is guaranteed to fail for C-level signal handlers), I would much prefer if the signal handler would be installed just once at startup.

@jdemeyer

Copy link
Copy Markdown
Contributor

Apart from the manipulation of the signal handlers, this code works fine for me and I would be happy to support this in cysignals.

@takluyver

Copy link
Copy Markdown
Member Author

I restore the default signal handler so that the default behaviour applies while user code is running. I tried installing it at the start and leaving it in place, but then SIGTERM during user code only exits once it would display the next prompt.

@jdemeyer

Copy link
Copy Markdown
Contributor

I restore the default signal handler so that the default behaviour applies while user code is running.

As you say yourself, this doesn't quite work when signal handlers have been installed at the C level.

I tried installing it at the start and leaving it in place, but then SIGTERM during user code only exits once it would display the next prompt.

I'd rather try to fix this instead...

@takluyver

Copy link
Copy Markdown
Member Author

It's easy enough to stop Python code by raising an exception, but if the main thread is inside some long running C code, I don't know of a good way to stop it on a signal from Python. I think setting it back to the default is the best option here, even if that means that people using C signal handlers have to disable our signal handling functionality.

I've brought this up on a Python issue here: http://bugs.python.org/issue13285

@Carreau

Carreau commented Jan 27, 2017

Copy link
Copy Markdown
Member

Added a change in the what's new.

@Carreau

Carreau commented Jan 27, 2017

Copy link
Copy Markdown
Member

I suggest we move forward with this even if it's not perfect. We can refine in 5.3 if needed.

@jdemeyer

Copy link
Copy Markdown
Contributor

I suggest we move forward with this even if it's not perfect. We can refine in 5.3 if needed.

Please no! This is going to break cysignals badly.

@jdemeyer

Copy link
Copy Markdown
Contributor

Or at least make catch_signal=False the default so nothing changes for existing use cases.

@jdemeyer

Copy link
Copy Markdown
Contributor

Another alternative: make it easy to change change_signal=False at runtime such that other packages which need to play with signals can do that.

@Carreau

Carreau commented Jan 27, 2017

Copy link
Copy Markdown
Member

Ok, so then should we bump to 5.3 ? This is one of the 2 remaining issues for 5.2.

@takluyver takluyver modified the milestones: 5.3, 5.2 Jan 28, 2017
@takluyver

Copy link
Copy Markdown
Member Author

Bumping to 5.3 so we can think more about this.

@Carreau

Carreau commented Feb 9, 2017

Copy link
Copy Markdown
Member

This PR have conflicts now. :-(

@takluyver takluyver modified the milestones: 5.3, 5.4 Feb 23, 2017
@Carreau

Carreau commented May 23, 2017

Copy link
Copy Markdown
Member

@takluyver, thoughts about this one ?

@takluyver

Copy link
Copy Markdown
Member Author

I don't think anyone wants it. I wrote it attempting to address a need @jdemeyer brought up, but it apparently makes things worse for him, not better. I don't think we can just set a Python signal handler and leave it, because a Python signal handler won't break out of compiled code which the user may have called.

Jeroen has implemented the machinery in Cysignals to restore OS-level signal handlers from Python, but we don't want a compiled dependency in IPython. And there doesn't seem to be much interest in getting that functionality into the Python signal module - though there isn't antipathy either, so maybe if someone made a pull request it might go somewhere.

Closing this for now, anyway.

@takluyver takluyver closed this May 24, 2017
@jdemeyer

Copy link
Copy Markdown
Contributor

In any case, I feel like this is mainly a prompt_toolkit issue (prompt-toolkit/python-prompt-toolkit#392)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants