Skip to content

Commit 709c9b6

Browse files
committed
kill old processes
1 parent 36f8262 commit 709c9b6

File tree

6 files changed

+64
-17
lines changed

6 files changed

+64
-17
lines changed

README.md

+6-11
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, build with [seleniumbase](https://seleniumbase.io/) and [FastAPI](https://fastapi.tiangolo.com).
44

5-
> [!WARNING]
5+
> [!CAUTION]
6+
> From now on, Byparr will clear all chrome processes longer than specified in `MAX_CHROME_LIFETIME` environment variable (default is 300 seconds). To disable this behavior, set `MAX_CHROME_LIFETIME` to `0`.
7+
8+
> [!IMPORTANT]
69
> Due to recent challenge changes, this software does not guarantee that the Cloudflare challenge will be bypassed. Cloudflare likely requires valid network traffic originating from the user’s public IP address to mark a connection as legitimate. While this tool may bypass the initial browser check, it does not ensure that requests will consistently pass Cloudflare's validation. More testing and data are required to understand how Cloudflare identifies connections and requests as valid. Invalid requests will result in Byparr's looping and eventually time-outing.
710
8-
> [!WARNING]
11+
> [!IMPORTANT]
912
> Support for NAS devices (like Synology) is minimal. Please report issues, but do not expect it to be fixed quickly. The only ARM device I have is a free Ampere Oracle VM, so I can only test ARM support on that. See [#22](https://github.com/ThePhaseless/Byparr/issues/22) and [#3](https://github.com/ThePhaseless/Byparr/issues/3)
1013
1114
> [!NOTE]
@@ -27,15 +30,7 @@ An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) a
2730

2831
### Docker Compose
2932

30-
```yaml
31-
services:
32-
byparr:
33-
image: ghcr.io/thephaseless/byparr:latest
34-
environment:
35-
- LOG_LEVEL=INFO # optional
36-
ports:
37-
- "8191:8191" # Optional if needed to make make requests/check docs on host
38-
```
33+
See `docker-compose.yaml`
3934

4035
### Docker
4136

docker-compose.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ services:
66
dockerfile: Dockerfile
77
environment:
88
- LOG_LEVEL=INFO
9+
- MAX_CHROME_LIFETIME=300
910
ports:
1011
- "8191:8191"

main.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212

1313
import src
1414
import src.utils
15+
from src.utils import consts
1516
import src.utils.consts
1617
from src.models.requests import LinkRequest, LinkResponse, Solution
1718
from src.utils import logger
18-
from src.utils.consts import LOG_LEVEL
19+
from src.utils.consts import LOG_LEVEL, kill_chromium_processes
1920

2021
app = FastAPI(debug=LOG_LEVEL == logging.DEBUG, log_level=LOG_LEVEL)
2122

@@ -25,18 +26,19 @@
2526
@app.get("/")
2627
def read_root():
2728
"""Redirect to /docs."""
28-
logger.info("Redirecting to /docs")
29+
logger.debug("Redirecting to /docs")
2930
return RedirectResponse(url="/docs", status_code=301)
3031

3132

3233
@app.get("/health")
3334
async def health_check():
3435
"""Health check endpoint."""
35-
logger.info("Health check")
36-
3736
health_check_request = read_item(
3837
LinkRequest.model_construct(url="https://prowlarr.servarr.com/v1/ping")
3938
)
39+
if consts.MAX_CHROME_LIFETIME>0:
40+
kill_chromium_processes()
41+
4042
if health_check_request.solution.status != HTTPStatus.OK:
4143
raise HTTPException(
4244
status_code=500,
@@ -66,9 +68,9 @@ def read_item(request: LinkRequest) -> LinkResponse:
6668
source = sb.get_page_source()
6769
source_bs = BeautifulSoup(source, "html.parser")
6870
title_tag = source_bs.title
69-
logger.info(f"Got webpage: {request.url}")
71+
logger.debug(f"Got webpage: {request.url}")
7072
if title_tag and title_tag.string in src.utils.consts.CHALLENGE_TITLES:
71-
logger.info("Challenge detected")
73+
logger.debug("Challenge detected")
7274
sb.uc_gui_click_captcha()
7375
logger.info("Clicked captcha")
7476

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ readme = "README.md"
1010
dependencies = [
1111
"beautifulsoup4==4.12.3",
1212
"fastapi[standard]==0.115.6",
13+
"psutil==6.1.0",
1314
"pyautogui==0.9.54",
1415
"pydantic==2.10.3",
1516
"seleniumbase==4.33.10",

src/utils/consts.py

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import logging
22
import os
3+
import time
4+
5+
import psutil
6+
7+
from src.utils import logger
38

49

510
def get_version_from_env():
@@ -21,12 +26,38 @@ def get_version_from_env():
2126

2227
return version_env.removeprefix("v")
2328

29+
def kill_chromium_processes():
30+
# Define the prefix and time threshold
31+
prefix = "chromium"
32+
time_threshold = 300 # 5 minutes in seconds
33+
34+
# Get the current time
35+
current_time = time.time()
36+
37+
# Iterate through all processes
38+
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
39+
try:
40+
# Extract process details
41+
pid = proc.info['pid']
42+
name:str = proc.info['name']
43+
create_time = proc.info['create_time']
44+
45+
# Check if the process name starts with the prefix and has been running longer than the threshold
46+
if name and name.startswith(prefix) and (current_time - create_time > time_threshold):
47+
logger.info(f"Terminating process {name} (PID: {pid}) running for {int(current_time - create_time)} seconds")
48+
psutil.Process(pid).terminate() # Terminate the process
49+
50+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
51+
# Ignore processes that no longer exist or can't be accessed
52+
pass
2453

2554
LOG_LEVEL = os.getenv("LOG_LEVEL") or "INFO"
2655
LOG_LEVEL = logging.getLevelNamesMapping()[LOG_LEVEL.upper()]
2756

2857
VERSION = get_version_from_env() or "unknown"
2958

59+
MAX_CHROME_LIFETIME= int(os.getenv("MAX_CHROME_LIFETIME", 300))
60+
3061

3162
CHALLENGE_TITLES = [
3263
# Cloudflare

uv.lock

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)