diff --git a/archivebox/cli/archivebox_update.py b/archivebox/cli/archivebox_update.py index 3b39f7ad..5ae26c33 100644 --- a/archivebox/cli/archivebox_update.py +++ b/archivebox/cli/archivebox_update.py @@ -206,12 +206,11 @@ def update( from archivebox.machine.models import Process from archivebox.core.shutdown_util import foreground_parent_watchdog, foreground_shutdown_signals from archivebox.services.supervision_service import ( - command_owns_runtime_stack, current_command, ensure_daemon_stack, standby_until_runtime_stack_needed, ) - from archivebox.workers.supervisord_util import stop_existing_supervisord_process + from archivebox.workers.supervisord_util import stop_existing_supervisord_process, stop_own_supervisord_process command = current_command(Process.TypeChoices.UPDATE, data_dir=CONSTANTS.DATA_DIR) @@ -414,8 +413,8 @@ def update( raise SystemExit(130) finally: command.mark_exited() - if stop_daemon_stack and command_owns_runtime_stack(command, data_dir=CONSTANTS.DATA_DIR): - stop_existing_supervisord_process() + if stop_daemon_stack: + stop_own_supervisord_process() def drain_old_archive_dirs(resume_from: str | None = None, batch_size: int = 100) -> dict[str, int]: diff --git a/archivebox/workers/supervisord_util.py b/archivebox/workers/supervisord_util.py index 2bb204d8..f96fd60c 100644 --- a/archivebox/workers/supervisord_util.py +++ b/archivebox/workers/supervisord_util.py @@ -506,6 +506,54 @@ def stop_existing_supervisord_process(): pass +def stop_own_supervisord_process(): + """Stop only the supervisord child started by this Python process.""" + + global _supervisord_proc + stop_grace_seconds = configured_stopwaitsecs(tuple(_desired_supervisord_workers.values())) + + if not _supervisord_proc or _supervisord_proc.poll() is not None: + reap_foreground_supervisord_process() + return False + + stopped_pid = _supervisord_proc.pid + try: + print(f"[🦸‍♂️] Stopping supervisord process (pid={stopped_pid})...") + try: + psutil_proc = psutil.Process(stopped_pid) + children = psutil_proc.children(recursive=True) + except psutil.NoSuchProcess: + children = [] + _supervisord_proc.terminate() + wait_popen_and_kill_children(_supervisord_proc, children, timeout=stop_grace_seconds) + try: + from archivebox.machine.models import Machine, Process + + for process in Process.objects.filter( + machine=Machine.current(), + process_type=Process.TypeChoices.SUPERVISORD, + status=Process.StatusChoices.RUNNING, + pwd=str(CONSTANTS.DATA_DIR), + pid=stopped_pid, + ).iterator(chunk_size=10): + process.mark_exited(exit_code=0) + except Exception: + pass + except (BrokenPipeError, OSError, psutil.TimeoutExpired): + pass + finally: + try: + SOCK_FILE = get_sock_file() + PID_FILE = SOCK_FILE.parent / PID_FILE_NAME + if PID_FILE.exists() and PID_FILE.read_text().strip() == str(stopped_pid): + PID_FILE.unlink(missing_ok=True) + SOCK_FILE.unlink(missing_ok=True) + except Exception: + pass + _supervisord_proc = None + return True + + def reap_foreground_supervisord_process() -> None: """Reap the supervisord child owned by this foreground parent if it exited.""" diff --git a/bin/take_screenshot.js b/bin/take_screenshot.js index 9b0f8771..31afcac4 100755 --- a/bin/take_screenshot.js +++ b/bin/take_screenshot.js @@ -23,6 +23,8 @@ Environment: SCREENSHOT_FULL_PAGE Set to 1 to capture the full page, defaults to viewport only SCREENSHOT_SCROLL_SELECTOR Scroll this selector into view before capture SCREENSHOT_WAIT_SELECTOR Wait for this selector before capture + SCREENSHOT_CLICK_SELECTOR Click this selector before capture + SCREENSHOT_AFTER_CLICK_WAIT_SELECTOR Wait for this selector after clicking SCREENSHOT_HOST_RESOLVER_RULES Chrome host resolver rules SCREENSHOT_SNAPSHOT_VIEW Set to list or grid before loading the page SCREENSHOT_RESET_FILTERS Set to 1 to clear the admin filter collapsed preference @@ -102,6 +104,13 @@ async function main() { if (process.env.SCREENSHOT_WAIT_SELECTOR) { await page.waitForSelector(process.env.SCREENSHOT_WAIT_SELECTOR, { timeout: 45000 }); } + if (process.env.SCREENSHOT_CLICK_SELECTOR) { + await page.waitForSelector(process.env.SCREENSHOT_CLICK_SELECTOR, { timeout: 45000 }); + await page.click(process.env.SCREENSHOT_CLICK_SELECTOR); + } + if (process.env.SCREENSHOT_AFTER_CLICK_WAIT_SELECTOR) { + await page.waitForSelector(process.env.SCREENSHOT_AFTER_CLICK_WAIT_SELECTOR, { timeout: 45000 }); + } if (process.env.SCREENSHOT_SCROLL_SELECTOR) { await page.waitForSelector(process.env.SCREENSHOT_SCROLL_SELECTOR, { timeout: 45000 }).catch(() => {}); await page.evaluate((selector) => {