diff --git a/main.ts b/main.ts index 261da06..09f42ff 100644 --- a/main.ts +++ b/main.ts @@ -1,7 +1,7 @@ import { parse } from "https://deno.land/std@0.188.0/flags/mod.ts"; import { load_settings } from "./config.ts"; import { check_file_permissions } from "./permissons.ts"; -import { TaskManager } from "./task_manager.ts"; +import { AlreadyClosedError, TaskManager } from "./task_manager.ts"; import { ParsedUrl, parseUrl, UrlType } from "./url.ts"; import { sure_dir } from "./utils.ts"; @@ -75,10 +75,12 @@ async function run() { async function main() { await sure_dir(settings.base); if (cmd == CMD.Download) { - download(); + await download(); } else if (cmd == CMD.Run) { - run(); + await run(); } } -main(); +main().catch((e) => { + if (!(e instanceof AlreadyClosedError)) throw e; +}); diff --git a/signal_handler.ts b/signal_handler.ts new file mode 100644 index 0000000..e58972f --- /dev/null +++ b/signal_handler.ts @@ -0,0 +1,8 @@ +import { TaskManager } from "./task_manager.ts"; + +export function add_exit_handler(m: TaskManager) { + const handler = () => { + m.close(); + }; + Deno.addSignalListener("SIGINT", handler); +} diff --git a/task_manager.ts b/task_manager.ts index 9a7bb55..a1b0c30 100644 --- a/task_manager.ts +++ b/task_manager.ts @@ -2,11 +2,16 @@ import { Client } from "./client.ts"; import { Config } from "./config.ts"; import { EhDb } from "./db.ts"; import { check_running } from "./pid_check.ts"; +import { add_exit_handler } from "./signal_handler.ts"; import { Task, TaskType } from "./task.ts"; import { download_task } from "./tasks/download.ts"; import { promiseState, PromiseStatus, sleep } from "./utils.ts"; +export class AlreadyClosedError extends Error { +} + export class TaskManager { + #closed = false; client; db; running_tasks: Map>; @@ -16,8 +21,13 @@ export class TaskManager { this.db = new EhDb(cfg.base); this.running_tasks = new Map(); this.max_task_count = cfg.max_task_count; + add_exit_handler(this); + } + #check_closed() { + if (this.#closed) throw new AlreadyClosedError(); } async add_download_task(gid: number, token: string) { + this.#check_closed(); const otask = await this.db.check_download_task(gid, token); if (otask !== undefined) { console.log("The task is already in list."); @@ -34,6 +44,7 @@ export class TaskManager { return await this.db.add_task(task); } async check_task(task: Task) { + this.#check_closed(); if (await this.check_task_is_running(task)) return; let t = task; if (task.pid !== Deno.pid) { @@ -44,6 +55,7 @@ export class TaskManager { return t; } async check_task_is_running(task: Task) { + this.#check_closed(); if (task.pid == Deno.pid) { return this.running_tasks.has(task.id); } else { @@ -52,6 +64,7 @@ export class TaskManager { } } async check_running_tasks() { + this.#check_closed(); const removed_task: number[] = []; for (const [id, task] of this.running_tasks) { const status = await promiseState(task); @@ -68,9 +81,12 @@ export class TaskManager { } } close() { + if (this.#closed) return; + this.#closed = true; this.db.close(); } async run() { + this.#check_closed(); while (1) { await this.check_running_tasks(); if (this.running_tasks.size == this.max_task_count) { @@ -94,6 +110,7 @@ export class TaskManager { } } run_task(task: Task) { + this.#check_closed(); if (task.type == TaskType.Download) { this.running_tasks.set( task.id,