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

Except AttributeError on sys.stdin.fileno() for Windows IIS10 #1947

Merged
merged 5 commits into from
Feb 29, 2024

Conversation

OSM1TT
Copy link
Contributor

@OSM1TT OSM1TT commented Apr 19, 2023

If you start uvicorn in the context of Windows IIS10 no stdin exists, but exception is not OSError, but AttributeError with uvicorn-0.21.1.dist-info

Summary

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.

[Montag 15:19] Fassel Andreas (BSH GDS-BCL3)


If you start uvicorn in the context of Windows IIS10 no stdin exists, but exception is not OSError, but AttributeError
with uvicorn-0.21.1.dist-info
@Kludex
Copy link
Member

Kludex commented Apr 19, 2023

I think we received a PR with this fix some time ago but it wasn't merged. We need to find out why... 🤔

@Kludex
Copy link
Member

Kludex commented Apr 22, 2023

If you start uvicorn in the context of Windows IIS10 no stdin exists

Can I see the logs at least? I can't find anywhere about this issue. Do you have any reference?

@Kludex Kludex added windows waiting author Waiting for author's reply labels Apr 22, 2023
@OSM1TT
Copy link
Contributor Author

OSM1TT commented Apr 24, 2023

add log, web.config and patch, thanks for your support.
encode-uvicorn-pull-1947.zip

@Kludex
Copy link
Member

Kludex commented Apr 24, 2023

Can you share it on the PR so I don't need to download anything?

@OSM1TT
Copy link
Contributor Author

OSM1TT commented Apr 24, 2023

python.log_9732_20234248231.log

INFO:     Will watch for changes in these directories: ['D:\\IIS\\DxxxCxP\\xxxcheck\\api']
INFO:     Uvicorn running on http://127.0.0.1:1133 (Press CTRL+C to quit)
INFO:     Started reloader process [12524] using WatchFiles
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\__main__.py", line 4, in <module>
    uvicorn.main()
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\main.py", line 403, in main
    run(
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\main.py", line 563, in run
    ChangeReload(config, target=server.run, sockets=[sock]).run()
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\supervisors\basereload.py", line 44, in run
    self.startup()
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\supervisors\basereload.py", line 77, in startup
    self.process = get_subprocess(
                   ^^^^^^^^^^^^^^^
  File "D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Lib\site-packages\uvicorn\_subprocess.py", line 37, in get_subprocess
    stdin_fileno = sys.stdin.fileno()
                   ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'fileno'

web.config.txt

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<system.webServer>
		<handlers accessPolicy="Read, Script">
			<add name="PythonHandler"
			     path="*"
			     verb="*"
			     modules="httpPlatformHandler"
			     resourceType="Unspecified"/>
		</handlers>
		<httpPlatform processPath="D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Scripts\python.exe"
		              arguments="-m uvicorn app:app --reload --log-level trace --port %HTTP_PLATFORM_PORT%"
		              startupTimeLimit="20"
		              startupRetryCount="2"
		              stdoutLogEnabled="true"
		              stdoutLogFile="D:\IIS\DxxxCxP\xxxcheck\logs\python.log"
		              processesPerApplication="4">
			<environmentVariables>
				<environmentVariable name="SERVER_PORT"
				                     value="%HTTP_PLATFORM_PORT%"/>
				<environmentVariable name="PATH"
				                     value="D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11\Scripts;%PATH%"/>
				<environmentVariable name="VIRTUAL_ENV"
				                     value="D:\IIS\DxxxCxP\xxxcheck\virtualpy3_11"/>
			</environmentVariables>
		</httpPlatform>
	</system.webServer>
</configuration>

_subprocess.pypatched.txt

"""
Some light wrappers around Python's multiprocessing, to deal with cleanly
starting child processes.
"""
import multiprocessing
import os
import sys
from multiprocessing.context import SpawnProcess
from socket import socket
from typing import Callable, List, Optional

from uvicorn.config import Config

multiprocessing.allow_connection_pickling()
spawn = multiprocessing.get_context("spawn")


def get_subprocess(
    config: Config,
    target: Callable[..., None],
    sockets: List[socket],
) -> SpawnProcess:
    """
    Called in the parent process, to instantiate a new child process instance.
    The child is not yet started at this point.

    * config - The Uvicorn configuration instance.
    * target - A callable that accepts a list of sockets. In practice this will
               be the `Server.run()` method.
    * sockets - A list of sockets to pass to the server. Sockets are bound once
                by the parent process, and then passed to the child processes.
    """
    # We pass across the stdin fileno, and reopen it in the child process.
    # This is required for some debugging environments.
    #stdin_fileno: Optional[int]
    try:
        stdin_fileno = sys.stdin.fileno()
    except (AttributeError, OSError):
        stdin_fileno = None

    kwargs = {
        "config": config,
        "target": target,
        "sockets": sockets,
        "stdin_fileno": stdin_fileno,
    }

    return spawn.Process(target=subprocess_started, kwargs=kwargs)


def subprocess_started(
    config: Config,
    target: Callable[..., None],
    sockets: List[socket],
    stdin_fileno: Optional[int],
) -> None:
    """
    Called when the child process starts.

    * config - The Uvicorn configuration instance.
    * target - A callable that accepts a list of sockets. In practice this will
               be the `Server.run()` method.
    * sockets - A list of sockets to pass to the server. Sockets are bound once
                by the parent process, and then passed to the child processes.
    * stdin_fileno - The file number of sys.stdin, so that it can be reattached
                     to the child process.
    """
    # Re-open stdin.
    if stdin_fileno is not None:
        sys.stdin = os.fdopen(stdin_fileno)

    # Logging needs to be setup again for each child.
    config.configure_logging()

    # Now we can call into `Server.run(sockets=sockets)`
    target(sockets=sockets)

@Kludex
Copy link
Member

Kludex commented Apr 25, 2023

I need you to paste the information on the PR. I'll not download any file.

@OSM1TT
Copy link
Contributor Author

OSM1TT commented Apr 25, 2023

I need you to paste the information on the PR. I'll not download any file.

Now I understand... see above

@Kludex Kludex removed the waiting author Waiting for author's reply label May 2, 2023
@OSM1TT
Copy link
Contributor Author

OSM1TT commented May 10, 2023

do you need support on this topic? What can i do to help you?

@Kludex
Copy link
Member

Kludex commented Feb 29, 2024

sys.stdin can be None sometimes, correct. See https://docs.python.org/3/library/sys.html#sys.__stdin__ for more information.

@Kludex Kludex enabled auto-merge (squash) February 29, 2024 20:36
@Kludex Kludex disabled auto-merge February 29, 2024 20:36
uvicorn/_subprocess.py Outdated Show resolved Hide resolved
@Kludex Kludex changed the title Update _subprocess.py Except AttributeError on sys.stdin.fileno() for Windows IIS10 Feb 29, 2024
@Kludex Kludex enabled auto-merge (squash) February 29, 2024 20:48
@Kludex Kludex merged commit 93897b5 into encode:master Feb 29, 2024
15 checks passed
@OSM1TT OSM1TT deleted the patch-1 branch July 5, 2024 07:08
@OSM1TT
Copy link
Contributor Author

OSM1TT commented Jul 5, 2024

👍

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

Successfully merging this pull request may close these issues.

2 participants