Skip to content

Commit

Permalink
fix: improve handling of network-related errors (Open-Wine-Components…
Browse files Browse the repository at this point in the history
…#191)

* umu_run: handle potential gaierror

- Resolving the domain name isn't sufficient when determining that the network of the host is in an unreachable state. In a certain unreachable network state where the domain can still be resolved, the program would still create the setup thread, which would cause the launcher to crash when making an http request to repo.steampowered.com

* treewide: add debug statements when making http requests
  • Loading branch information
R1kaB3rN authored Sep 22, 2024
1 parent e42043a commit 3e71418
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
2 changes: 1 addition & 1 deletion umu/umu_proton.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get_umu_proton(
STEAM_COMPAT.mkdir(exist_ok=True, parents=True)

try:
log.debug("Sending request to api.github.com")
log.debug("Sending request to 'api.github.com'...")
assets = _fetch_releases()
except URLError:
log.debug("Network is unreachable")
Expand Down
47 changes: 31 additions & 16 deletions umu/umu_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from pathlib import Path
from pwd import getpwuid
from re import match
from socket import AF_INET, SOCK_DGRAM, socket
from socket import AF_INET, SOCK_DGRAM, gaierror, socket
from subprocess import Popen
from typing import Any

Expand Down Expand Up @@ -687,7 +687,6 @@ def run_command(command: tuple[Path | str, ...]) -> int:

def main() -> int: # noqa: D103
args: Namespace | tuple[str, list[str]] = parse_args()
future: Future | None = None
env: dict[str, str] = {
"WINEPREFIX": "",
"GAMEID": "",
Expand Down Expand Up @@ -715,6 +714,7 @@ def main() -> int: # noqa: D103
"UMU_RUNTIME_UPDATE": "",
}
opts: list[str] = []
prereq: bool = False
root: Traversable

try:
Expand Down Expand Up @@ -745,16 +745,16 @@ def main() -> int: # noqa: D103
log.addHandler(console_handler)
log.setLevel(level=DEBUG)

# Setup the launcher and runtime files
# An internet connection is required for new setups
with ThreadPoolExecutor() as thread_pool:
try:
# Test the network environment and fail early if the user is trying
# to run umu-run offline because an internet connection is required
# for new setups
log.debug("Connecting to '1.1.1.1'...")
with socket(AF_INET, SOCK_DGRAM) as sock:
sock.settimeout(5)
sock.connect(("1.1.1.1", 53))
future = thread_pool.submit(
setup_umu, root, UMU_LOCAL, thread_pool
)
prereq = True
except TimeoutError: # Request to a server timed out
if not UMU_LOCAL.exists() or not any(UMU_LOCAL.iterdir()):
err: str = (
Expand All @@ -763,22 +763,31 @@ def main() -> int: # noqa: D103
)
raise RuntimeError(err)
log.debug("Request timed out")
prereq = True
except OSError as e: # No internet
if (
e.errno == ENETUNREACH
and not UMU_LOCAL.exists()
or not any(UMU_LOCAL.iterdir())
):
if e.errno != ENETUNREACH:
raise
if not UMU_LOCAL.exists() or not any(UMU_LOCAL.iterdir()):
err: str = (
"umu has not been setup for the user\n"
"An internet connection is required to setup umu"
)
raise RuntimeError(err)
if e.errno != ENETUNREACH:
raise
log.debug("Network is unreachable")
prereq = True

if not prereq:
err: str = (
"umu has not been setup for the user\n"
"An internet connection is required to setup umu"
)
raise RuntimeError(err)

# Setup the launcher and runtime files
future: Future = thread_pool.submit(
setup_umu, root, UMU_LOCAL, thread_pool
)

# Check environment
if isinstance(args, Namespace):
env, opts = set_env_toml(env, args)
else:
Expand All @@ -797,8 +806,14 @@ def main() -> int: # noqa: D103
log.info("%s=%s", key, val)
os.environ[key] = val

if future:
try:
future.result()
except gaierror as e:
# Name resolution error in the request to repo.steampowered.com
# At this point, umu was already setup and user is offline
if e.errno != -3:
raise e
log.debug("Name resolution failed")

# Exit if the winetricks verb is already installed to avoid reapplying it
if env["EXE"].endswith("winetricks") and is_installed_verb(
Expand Down
1 change: 1 addition & 0 deletions umu/umu_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ def _update_umu(
)
token: str = f"?version={token_urlsafe(16)}"
log.debug("Existing install detected")
log.debug("Sending request to '%s'...", client_session.host)

# Find the runtime directory (e.g., sniper_platform_0.20240530.90143)
# Assume the directory begins with the alias
Expand Down

0 comments on commit 3e71418

Please sign in to comment.