Skip to content
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

Close background process if IDLE closes abnormally. #58645

Closed
asvetlov opened this issue Mar 29, 2012 · 12 comments
Closed

Close background process if IDLE closes abnormally. #58645

asvetlov opened this issue Mar 29, 2012 · 12 comments
Assignees
Labels
topic-IDLE type-bug An unexpected behavior, bug, or error

Comments

@asvetlov
Copy link
Contributor

BPO 14440
Nosy @terryjreedy, @serwy, @asvetlov, @roseman
Files
  • issue14440.patch
  • issue14440_rev2.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/asvetlov'
    closed_at = <Date 2019-05-03.19:23:08.618>
    created_at = <Date 2012-03-29.13:28:32.023>
    labels = ['expert-IDLE', 'type-bug']
    title = 'Close background process if IDLE closes abnormally.'
    updated_at = <Date 2019-05-03.19:23:08.617>
    user = 'https://github.com/asvetlov'

    bugs.python.org fields:

    activity = <Date 2019-05-03.19:23:08.617>
    actor = 'asvetlov'
    assignee = 'asvetlov'
    closed = True
    closed_date = <Date 2019-05-03.19:23:08.618>
    closer = 'asvetlov'
    components = ['IDLE']
    creation = <Date 2012-03-29.13:28:32.023>
    creator = 'asvetlov'
    dependencies = []
    files = ['25105', '25112']
    hgrepos = []
    issue_num = 14440
    keywords = ['patch']
    message_count = 12.0
    messages = ['157043', '157164', '157170', '157209', '157221', '157225', '157245', '157271', '157393', '157420', '157449', '341353']
    nosy_count = 4.0
    nosy_names = ['terry.reedy', 'roger.serwy', 'asvetlov', 'markroseman']
    pr_nums = []
    priority = 'normal'
    resolution = 'out of date'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue14440'
    versions = ['Python 2.7', 'Python 3.3', 'Python 3.4']

    @asvetlov
    Copy link
    Contributor Author

    Now if IDLE was ran from console and then terminated by <Ctrl-\> or kill signal — background process keep living forever.

    That process have to stop itself if there are no frontend IDLE.

    @asvetlov asvetlov self-assigned this Mar 29, 2012
    @terryjreedy
    Copy link
    Member

    You need to specify os (with version) *nix?
    There have been issues like this before, for earlier Python version, at least for Windows XP, which have been fixed, at least for Windows. I think last patch (a year ago? before 3.2 I think) switched to using subprocess instead of older methods. If I kill Idle with task manager, the other, background pythonw process dies in under half a second.
    (If background process dies, IDLE restarts.)

    @asvetlov
    Copy link
    Contributor Author

    I use Ubuntu Linux 11.10

    Hmm, you are right: background process dies. But I'm pretty sure when I worked on IDLE bugs three weeks ago sometimes that process remained to live forever.

    Aahh.
    At least sending SIGTERM (kill -9) to foreground IDLE process doesn't delete background. Also the same if foreground hangs by some error in code and should be killed from console. <Ctrl-C> doesn't help in this particular case, <Ctrl+\> (SIGQUIT) terminates foreground but background lives forever.

    @asvetlov asvetlov added the type-bug An unexpected behavior, bug, or error label Mar 31, 2012
    @serwy
    Copy link
    Mannequin

    serwy mannequin commented Mar 31, 2012

    I can confirm this problem with Ubuntu 11.04.

    @terryjreedy
    Copy link
    Member

    Andrew: I strongly agree with the goal that IDLE should not leave zombie processes. The background process should die if either 1) IDLE restarts the shell with a new background process, as with every edit-run cycle, or 2) IDLE dies. The desired behavior seems to be both somewhat fragile and system dependent. I do not know whether 100% compliance on every system is sensibly possible.

    The issue I referred to is bpo-12540. The problem there was worse: leaving a zombie for every shell restart on Windows. Perhaps the discussion there will give you some ideas.

    Ctrl-\ does not seem to do anything on Windows. I do not know whether TaskManager 'Terminate process' corresponds to *nix SIGTERM, SIGQUIT, SIGKILL, something else, or is completely Windows specific.

    @asvetlov
    Copy link
    Contributor Author

    Terry, sorry.

    That's definitely posix-specific bug. I'll make a patch assuming Windows works well with killing IDLE.

    To be polite I'll describe used signal names shortly.

    SIGKILL, SIGTERM, SIGINT and SIGQUIT are used to stop process.
    — SIGKILL is mimic to Windows TerminateProcess in some way.
    It cannot be overloaded by target process and unconditionally terminates one.
    — SIGTERM is default signal for kill utility. Used to stop process by some program.
    — SIGINT sent if user press Ctrl+C in terminal.
    Overridden very often.
    Python does it itself to translate this signal to KeyboardInterrupt exception.
    — SIGQUIT bound to Ctrl+\ and used to stop program with memory dump.
    The standard way to process it
    (if need to, the most programs leaves that handler untouched) is:
    close used resources and maybe write to stderr/logs some message.
    Usually SIGQUIT sent to hang program to stop execution
    if Ctrl+C doesn't help but potentially dangerous SIGKILL is not desirably
    by risk of lacking important data or locking kernel objects.

    @terryjreedy
    Copy link
    Member

    Just a bit more info: ^D and ^\ in Command Prompt interpreter print '^D' or '^\'. Return causes syntax error. ^Z\n in interpreter causes silent close. (Because DOS used ^Z as end-of-file.)

    ^D in IDLE causes silent close. IDLE ignores ^\ and ^Z both -- nothing printed or stored. Following \n gets prompt back. The difference is not nice for Windows users, but I presume IDLE behavior is same as on *nix and consider consistency across platforms good and should be kept.

    If I understand, IDLE needs to install a SIGQUIT handler to terminate the background process 'resource'. That should work on Windows too as either SIGQUIT will never happens, or if it does, same should happen on Windows too. I know SIGKILL cannot be caught. What about SIGTERM?

    @asvetlov
    Copy link
    Contributor Author

    asvetlov commented Apr 1, 2012

    We can install signal handlers for everything what can stop process but I prefer to pass IDLE pid to subintepreter and periodically check for prime process existing.

    @serwy
    Copy link
    Mannequin

    serwy mannequin commented Apr 3, 2012

    This bug is related to bpo-12540. The approach taken there is to have the IDLE frontend explicitly kill the subprocess. It's a band-aid to the problem that run.py doesn't exit when the socket to the IDLE frontend closes (either by shell restart or kill -9 on IDLE).

    Attached is a patch to cause the subprocess to exit. I have to admit not fully understanding why it works (on Ubuntu 11.04).

    It looks like the following code in _getresponse() in rpc.py is what keeps the subprocess running:

        cvar.acquire()
        while myseq not in self.responses:
            cvar.wait()

    I also tried disabling the "terminate_subprocess" in PyShell.py. With that change, the subprocess does not terminate on a shell restart (unless my patch is applied).

    Andrew, Terry: What are your thoughts?

    @asvetlov
    Copy link
    Contributor Author

    asvetlov commented Apr 3, 2012

    I still prefer to check in subprocess for parent proc existing.

    @serwy
    Copy link
    Mannequin

    serwy mannequin commented Apr 4, 2012

    Andrew, the reason the subprocess is not closing is due to a thread management problem. I found that a dummy thread handles cvar.wait() which is why the subprocess fails to terminate properly.

    If you change the tight loop in _getresponse to be:

        while myseq not in self.responses:
            print(threading.enumerate(), file=sys.__stderr__)
            sys.__stderr__.flush()
            cvar.wait(1)

    Then you'll get the following dumped to the terminal once a second:
    [<_DummyThread(Dummy-1, started daemon 139991862630176)>, <Thread(SockThread, started daemon 139991766066944)>]

    The MainThread already stopped, but these two daemon threads don't terminate, which is strange. Is this a bug in itself?

    Polling the OS for the IDLE frontend process will give an indication to terminate the subprocess, but actually terminating the subprocess from within the subprocess is the main problem.

    Attached is a patch which takes a different approach to terminating the subprocess by using .shutdown instead.

    @asvetlov
    Copy link
    Contributor Author

    asvetlov commented May 3, 2019

    outdated

    @asvetlov asvetlov closed this as completed May 3, 2019
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    topic-IDLE type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants