{"id":30202979,"url":"https://github.com/monoid/interruptable","last_synced_at":"2025-08-13T11:13:57.882Z","repository":{"id":62440996,"uuid":"449562833","full_name":"monoid/interruptable","owner":"monoid","description":"Interruptable Read and Write wrappers in Rust","archived":false,"fork":false,"pushed_at":"2022-01-19T11:07:28.000Z","size":6,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-11T06:26:36.961Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monoid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-19T05:44:47.000Z","updated_at":"2022-11-16T16:37:21.000Z","dependencies_parsed_at":"2022-11-01T21:53:54.283Z","dependency_job_id":null,"html_url":"https://github.com/monoid/interruptable","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/monoid/interruptable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monoid%2Finterruptable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monoid%2Finterruptable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monoid%2Finterruptable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monoid%2Finterruptable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monoid","download_url":"https://codeload.github.com/monoid/interruptable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monoid%2Finterruptable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270228631,"owners_count":24548875,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-13T02:00:09.904Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-13T11:13:48.168Z","updated_at":"2025-08-13T11:13:57.823Z","avatar_url":"https://github.com/monoid.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# interruptable\nInterruptable `Read` and `Write` wrappers in Rust\n\n## Usage \n\nThis package is to be used for interrupting IO in conjunction with\nsignal handling crates like `ctrlc`.  These crates do handle received\nsignals and allow to set some flag, but if application code is performing\nIO, it will not able to check the flag until it completes.  The Unix-like\nOSes do interrupt IO operations on signals, returning `EINT` errno (aka \n`ErrorKind::Interrupted`), but `std::io` utility methods sliently restart\nsuch operations.\n\nThe `Interruptable` wrapper for `std::io::Read` and `std::io::Write` checks\nthe flag (`std::sync::atomic::AtomicBool`) on each `read` or `write` operation,\nand when it sees that flag is set, it returns `std::io::Error` (standard error\nfor the IO operations) with `std::io::ErrorKind::Other` and nested error of\n`ErrorKind::Interrupted`, thus hiding it from the retrying logic.\n\nLife without `interruptabe`:\n\n``` rust,ignore\nuse std::io;\nuse std::sync::atomic;\nuse ctrlc;\n\nlet interrupt_flag = atomic::Arc::new(atomic::AtomicBool::new(false));\nlet interrput_flag2 = interrupt_flag.clone();\n\nctrlc::set_handler(move || {\n    interrput_flag2.store(true, std::sync::atomic::Ordering::SeqCst);\n}).unwrap();\n\nlet file = io::BufReader::new(\n   std::fs::File::open(\"/path/to/slow/media/data.data\")?\n);\n\nlet my_precious_resource = MyResource::new();\n\nfor line in file.lines() {\n    // It will be checked only after whole line is read, that may\n    // take arbitrary long time.\n    if interrput_flag2.load(std::sync::atomic::Ordering::SeqCst) {\n        std::mem::drop(my_precious_resource);\n        std::process::exit(42);\n    }\n    let line = line?;\n    ...\n}\n```\n\nLife with `interruptabe`:\n\n``` rust,ignore\nuse std::io;\nuse std::sync::atomic;\nuse ctrlc;\n\nlet interrupt_flag = atomic::Arc::new(atomic::AtomicBool::new(false));\nlet interrput_flag2 = interrupt_flag.clone();\n\nctrlc::set_handler(move || {\n    interrput_flag2.store(true, std::sync::atomic::Ordering::SeqCst);\n}).unwrap();\n\nlet file = io::BufReader::new(\n    // Work both for Read and Write.\n    interruptable::Interruptable::new(\n        std::fs::File::open(\"/path/to/slow/media/data.data\")?,\n        interrupt_flag,\n    )\n);\n\nlet my_precious_resource = MyResource::new();\n\nfor line in file.lines() {\n    // When the signal will arrive and flag is set, line will be Err(...)\n    // immediately, thus you will be able to handle it and gracefully\n    // shutdown your application: my_precious_resource is destroyed\n    // in the standard way, by Drop::drop.\n    let line = line?;\n    ...\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonoid%2Finterruptable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonoid%2Finterruptable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonoid%2Finterruptable/lists"}