ZhuLinsen/daily_stock_analysis · error · RuntimeError

题材新闻搜索进程未返回结果

Error message

题材新闻搜索进程未返回结果

What it means

RuntimeError raised when parent_conn.recv() hits EOFError: the worker process closed its end of the pipe without sending the (ok, value) result tuple — i.e. it died (crash, kill, OOM, interpreter abort) instead of returning or raising through the protocol. Distinct from a timeout: the pipe signaled EOF, not silence.

Source

Thrown at src/search_service.py:145

                daemon=True,
            )
            process.start()
            process_started = True
            child_conn.close()
            child_conn = None

            poll_seconds = (
                wait_seconds
                if deadline is None
                else max(0.0, deadline - time.monotonic())
            )
            if poll_seconds <= 0 or not parent_conn.poll(poll_seconds):
                _terminate_search_process(process)
                raise TimeoutError(f"题材新闻搜索超过 {wait_seconds:g}s,已终止请求进程")
            try:
                ok, value = parent_conn.recv()
            except EOFError as exc:
                raise RuntimeError("题材新闻搜索进程未返回结果") from exc
        finally:
            try:
                if child_conn is not None:
                    child_conn.close()
            finally:
                try:
                    if parent_conn is not None:
                        parent_conn.close()
                finally:
                    if process_started:
                        try:
                            process.join(_SEARCH_TIMEOUT_PROCESS_JOIN_GRACE_SECONDS)
                        finally:
                            _terminate_search_process(process)
    finally:
        # Capacity belongs to the accepted call, not to a successfully started
        # process. Release it even if Process.start() or cleanup itself fails.
        _SEARCH_TIMEOUT_WORKER_SLOTS.release()

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Check process-level logs (dmesg for OOM-kill, container restart events) for why the worker died
  2. Retry once — a one-off crash may not reproduce; persistent EOF on the same topic indicates a deterministic bug
  3. Reproduce by running the provider chain in-process for the failing topic to surface the real traceback
  4. Raise memory limits or reduce per-search result volume if the worker is being OOM-killed
Defensive patterns

Strategy: try-catch

Try / catch

try:
    resp = search_topic_news(topic)
except RuntimeError as exc:
    if "未返回结果" in str(exc):
        log.error("Search worker died for topic %r — check OOM/crash logs", topic)
        run_provider_chain_in_process_for_debug(topic)  # surface real traceback
    raise

Prevention

When it happens

Trigger: The subprocess worker raising an unhandled exception that kills the process before send, being OOM-killed by the kernel, terminated externally (container limits, supervisor), or aborting during native-code scraping dependencies (segfault in a parser).

Common situations: Memory limits in containers killing the worker; an unhandled error path in a provider only triggered by specific topics; native dependency crashes (lxml/ICU mismatches); SIGTERM from orchestration during a run.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/242de7951bce67ba. Report an issue: GitHub.