From e52026d2b215fe9ac76d61b6ce50feac6f27fc54 Mon Sep 17 00:00:00 2001 From: jze9 Date: Thu, 9 Jul 2026 11:51:21 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0:=20=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20=D0=BE?= =?UTF-8?q?=D0=B4=D0=BD=D1=83=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=BF=D1=80=D1=8F=D0=BC=D1=83=D1=8E=20=E2=80=94=20?= =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=20=D0=B2=D0=B5=D1=87=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=20=D0=B2=20join()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Редкая гонка spawn+mp.Queue вешала главный процесс НАВЕЧНО после полировки (22.5 часа простоя; /proc/*/stack: главный в do_wait, polish-писатель в pipe_read — данные из очереди не доехали). Для одной записи процесс-писатель и очередь не нужны вовсе: конкурентных писателей в этот момент нет, пишем insert_run'ом напрямую. Плюс возврат SIGTERM к SIG_DFL после дренажа — иначе фаза полировки неубиваема мягко. Co-Authored-By: Claude Fable 5 --- src/gausse/optim/evolutionary.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/gausse/optim/evolutionary.py b/src/gausse/optim/evolutionary.py index e6a5bb7..5913f05 100644 --- a/src/gausse/optim/evolutionary.py +++ b/src/gausse/optim/evolutionary.py @@ -22,7 +22,7 @@ from gausse.optim import worker_context from gausse.optim.objective import EvaluationResult, build_run_record, evaluate from gausse.optim.progress_log import ProgressLogger, default_log_path from gausse.optim.search_space import Genome, SearchBounds, crossover, mutate, repair, sample_genome -from gausse.storage.database import run_writer_process +from gausse.storage.database import insert_run, open_connection, run_writer_process from gausse.storage.schema import RunRecord @@ -204,6 +204,9 @@ def run_evolution( # «Exception ignored … sem_unlink FileNotFoundError» после каждого цикла queue.close() queue.join_thread() + # после дренажа возвращаем обработку SIGTERM по умолчанию: иначе + # процесс в фазе полировки нельзя остановить мягко (только SIGKILL) + signal.signal(signal.SIGTERM, signal.SIG_DFL) logger._write("база дописана полностью") assert best_pair is not None @@ -214,14 +217,17 @@ def run_evolution( polished_genome, polished_result = polish_best(best_genome, db, bounds) logger._write(f"полировка готова: КПД {best_result.fitness*100:.2f}% -> {polished_result.fitness*100:.2f}%") if polished_result.fitness > best_result.fitness: - conn_queue = ctx.Queue() - polish_writer = ctx.Process(target=run_writer_process, args=(conn_queue, db_path)) - polish_writer.start() - conn_queue.put(build_run_record(polished_genome, polished_result, db, search_mode="evolve-polish")) - conn_queue.put(None) - polish_writer.join() - conn_queue.close() - conn_queue.join_thread() + # ОДНУ запись пишем напрямую, без процесса-писателя и очереди: + # конкурентных писателей в этот момент нет (основной уже завершён), + # а редкая гонка spawn+Queue вешала главный процесс в join() + # НАВЕЧНО (22.5 часа простоя, пойман по /proc/*/stack: главный в + # do_wait, писатель в pipe_read — данные из очереди не доехали). + conn = open_connection(db_path) + try: + insert_run(conn, build_run_record(polished_genome, polished_result, db, search_mode="evolve-polish")) + finally: + conn.close() + logger._write("полированный геном записан в базу") best_genome, best_result = polished_genome, polished_result return {