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

Python 3.12: Shiny refuses to shut down until all network connections are closed #771

Open
daattali opened this issue Oct 19, 2023 · 30 comments

Comments

@daattali
Copy link

I just installed py-shiny on a fresh Windows installation. I'm getting an issue where any time the shiny app is killed, the terminal freezes. If I run a shiny app with shiny run, then when I press ctrl+C I see messages saying that the shiny app is attempting to shut down, but the terminal gets stuck and never returns to the prompt.

If I run in --reload mode, then the moment I change a file and save it, the terminal gets to the same state.

This happens in the command line and also in VSCode.

(venv) C:\Users\Dean\Documents\R\python\shinytest>shiny run
←[32mINFO←[0m:     Started server process [←[36m16176←[0m]
←[32mINFO←[0m:     Waiting for application startup.
←[32mINFO←[0m:     Application startup complete.
←[32mINFO←[0m:     Uvicorn running on ←[1mhttp://127.0.0.1:8000←[0m (Press CTRL+C to quit)
←[32mINFO←[0m:     127.0.0.1:49687 - "←[1mGET / HTTP/1.1←[0m" ←[32m200 OK←[0m
←[32mINFO←[0m:     ('127.0.0.1', 49689) - "WebSocket /websocket/" [accepted]
←[32mINFO←[0m:     connection open
←[32mINFO←[0m:     127.0.0.1:49688 - "←[1mGET / HTTP/1.1←[0m" ←[32m200 OK←[0m
←[32mINFO←[0m:     connection closed
←[32mINFO←[0m:     ('127.0.0.1', 49695) - "WebSocket /websocket/" [accepted]
←[32mINFO←[0m:     connection open
←[32mINFO←[0m:     Shutting down
@daattali
Copy link
Author

daattali commented Oct 19, 2023

(As you can see from the logs, it would also be nice to fix #162 because this is a terrible experience on Windows, it gives me the feeling that Windows users are not meant to use py-shiny)

@j-lim-sigma
Copy link

Hi, I experienced the same thing using python 3.12 on MacOS. It works fine with 3.11 though, both with --reload and without.

@jcheng5
Copy link
Collaborator

jcheng5 commented Oct 21, 2023

@j-lim-sigma Thank you, I'm installing 3.12 now to try to repro.

@daattali Any chance you're on Python 3.12 as well?

@daattali
Copy link
Author

Yes I am indeed on 3.12. I can try to install 3.11 later if I find very simple instructions for it :)

@jcheng5
Copy link
Collaborator

jcheng5 commented Oct 22, 2023

I can repro on macOS 3.12 if I still have a connected browser. Once I close the browser, the command line returns. I get the same thing if I run the command uvicorn app:app instead of shiny run.

Edit: on Windows, it stays hung even after the browser closes.

Edit 2: on Windows, the command line returns if I close the whole browser. It's like an open socket is keeping Python alive.

@jcheng5
Copy link
Collaborator

jcheng5 commented Oct 22, 2023

Here is a discussion on Uvicorn and a suggested fix, no response yet: encode/uvicorn#2122

@jcheng5 jcheng5 changed the title Windows: terminal freezes when a shiny app shuts down Python 3.12: Shiny refuses to shut down until all network connections are closed Oct 22, 2023
@jcheng5
Copy link
Collaborator

jcheng5 commented Oct 22, 2023

FWIW, I tried daphne (daphne app:app) and hypercorn (hypercorn app:app) under Python 3.12 and they both served up my app fine and exited cleanly. So this appears to be specific to uvicorn.

@daattali
Copy link
Author

Here is a discussion on Uvicorn

Maybe it should be upgraded to an "Issue" in oder for the uvicorn team to notice?

@daattali
Copy link
Author

I can confirm that downgrading to python 3.11 fixes this

@jcheng5
Copy link
Collaborator

jcheng5 commented Nov 1, 2023

This PR contains the fix. Thanks for your patience! encode/uvicorn#2145

@ME-researchgroup
Copy link

I am experiencing this issue using python 3.10.4 on windows.
I have to kill the terminal to stop shiny from running after hitting ctrl+c

@corey-dawson
Copy link

Similar issue on python 3.10.13. Sometimes the process shuts down normally, sometimes the terminal freezes. for me. Have to close the terminal and reopen a new one. this is where mine gets stuck, but only maybe half the time:

image

@jcheng5
Copy link
Collaborator

jcheng5 commented Feb 27, 2024

@corey-dawson Does it happen even with the simplest Shiny app?

from shiny.express import input, render, ui

ui.input_slider("n", "N", 0, 100, 20)


@render.text
def txt():
    return f"n*2 is {input.n() * 2}"

@gza-austin-elliott
Copy link

gza-austin-elliott commented May 16, 2024

Similar issue and symptoms as @corey-dawson above.

Windows 10.0.19045
Python 3.12

Fires up perfectly every time, but CTRL+C terminate does not consistently work. Occasionally requires full kill on the terminal to shut down. Something additional I haven't seen above which seems related is the terminal's outputs seem to freeze up when it fires up in this bugged mode. That is to say, I can tell when I'll have to kill the terminal rather than CTRL+C to shut down because the terminal will not display simple debug statements onstart.

Ex

# server logic

def server(input: Inputs, output: Outputs, session: Session):

    session_data = {}
    
    tables_trigger = reactive.Value(None) #init triggers
    
    data_trigger = reactive.Value(None) #init triggers
    
    ...[MORE CODE]...
    
    print("debug: export_button function defined")  # debug

In a non-bugged startup this print statement displays in my terminal and the processes properly exit on CTRL+C. In a bugged startup this print statement does not display and the processes do not exit on CTRL+C.

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

Does it happen with the simple app I posted in my previous comment?

@gza-austin-elliott
Copy link

Does it happen with the simple app I posted in my previous comment?

It does not seem to. Did a fresh venv + your app and it initializes/terminates properly every time.

The app I was initially encountering this issue with was built on shiny.core. I quickly changed your example code over to shiny.core and tested and that also checked out, terminated fine with CRTL+C every time.

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

I don’t suppose you can share your source code with us? Either publicly or privately? If not, trying to find a reproducible example you can share would be a huge help.

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

Can you also try pip install -U uvicorn?

@gza-austin-elliott
Copy link

I jumped back to my original source code to prep it to share and in retesting I could not recreate the issue. Very strange. I did not restart VSC, just changed from project to project. I'll keep an eye out and see if I can recreate it and pay closer attention to potential environmental variables.

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

@gza-austin-elliott I don't know if your Python version varies from project to project, but if so, I've noticed the Ctrl+C handling changed in Python 3.11+ in a way that would probably be highly relevant to this issue.
https://docs.python.org/3/library/asyncio-runner.html#handling-keyboard-interruption

Although the way they implementated that change, it is supposed to interrupt immediately if you hit Ctrl+C twice, which sounds like wasn't working for you, so maybe not...

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

If you still have a project where you can reproduce it, and are up for it, I'd be happy to jump on a zoom session with you and pair debug it. This is a scary problem for us to leave undiagnosed.

@ME-researchgroup
Copy link

ME-researchgroup commented May 16, 2024

I still experience this issue very sporadically. It seems to occur a lot less frequently compared to earlier versions of py-shiny. CTRL+C multiple times does not work either when it hangs (python 3.12.3).

It is very difficult to reproduce because it seemingly occurs at random. Perhaps you can find a way to test this behavior via a script to run it a lot of times..

@jcheng5
Copy link
Collaborator

jcheng5 commented May 16, 2024

@ME-researchgroup Are you still on Python 3.10?

(On Python 3.11+) When asyncio is active, a single Ctrl+C makes a gentle suggestion to the current task that maybe it should interrupt at an opportune time. A second Ctrl+C is supposed to raise a KeyboardInterrupt on the main thread. Perhaps we should install our own Ctrl+C handler where if you do it four times in quick succession, we terminate the process. Very unsatisfying but I hate the idea of people having to go to Task Manager.

@ME-researchgroup
Copy link

No I am currently on python 3.12.

Having a custom KeyboardInterrupt handler is not a bad idea to clean up the long asyncio stack trace it currenly throws. Could make it feel a bit cleaner. Though I doubt that pressing Ctrl+C four times in quick succession to work around the process getting stuck is the right approach. What happens to any custom code that is supposed to run atexit if the process gets killed, for instance?

You dont actually have to go to Task Manager to kill a terminal, by the way.

@ME-researchgroup
Copy link

Looks like the issue could be in watchfiles @jcheng5

recording_shiny_issue.zip

@jcheng5
Copy link
Collaborator

jcheng5 commented May 17, 2024

Oh, wait, wait. So when you hit Ctrl+C it does show KeyboardInterrupt, but the process doesn't exit?

@ME-researchgroup
Copy link

Yes. But I definitely remember getting stuck on the "Finished server process" message without the KeyboardInterrupt as someone mentioned above. That may not be the case anymore in a newer version of shiny or python, I havent paid much attention I must admit. I'll keep an eye out to see if it also still happens for me without the KeyboardInterrupt trace.

@ME-researchgroup
Copy link

My findings over the last week:

  • I always get the KeyboardInterrupt error in python 3.12 when it hangs.
  • Code that I have defined to run atexit always executes.
  • The reloader process is the only thing that does not want to terminate. Watchfiles stays active and this message is never displayed:
    INFO: Stopping reloader process [15456]

Hope this helps!

@jcheng5
Copy link
Collaborator

jcheng5 commented May 25, 2024

I’m at a loss. Are you able to reproduce this reliably enough that a live debugging session might be productive?

@ME-researchgroup
Copy link

Afraid not.. are there any debugging steps you'd like me to go through when I encounter the issue?

I could also send you a message when it happens to see if you (or someone else from the team) are available for a meeting.

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

No branches or pull requests

6 participants