The walk records a path as a regular file. If it is a FIFO (or a device node whose open blocks) by the time a hash worker opens it, os.Open blocks until a writer appears, which never happens. The worker never returns a result, so the phase waits forever, the lock stays held, and every later cron scan fails with another scan is running. The first SIGINT does not end it: readRuns returns, but the deferred pool.stop() waits for the blocked worker, so the hashed records still in the batch are never committed; only a second signal (uncaught, status 130) ends the process, leaving the database in WAL mode. The README says per-file errors never abort the run and that the first signal stops the scan cleanly.
Reproduce: 302 same-size 9 MiB files, scan --workers 1; when the hash: line appears, rm the two files with the highest inode numbers and mkfifo them in their place. The bar stops at [300/302]; one thread sleeps in wait_for_partner; SIGINT prints nothing more; a second SIGINT ends it with status 130, an empty database and -wal/-shm files left behind.
Definition of done
The hash and content phases open without blocking (O_NONBLOCK or equivalent) and check with fstat that the open file is regular; anything else is a per-path error: warned about, counted as skipped, no record written.
A test that swaps a walked regular file for a FIFO before it is read fails before the fix (hangs until the test timeout) and passes after (one warning, exit 0).
Severity: minor. It needs a regular file replaced by a FIFO or blocking device between the walk and the read; the outcome is a scan that never ends and holds the lock until killed.
Model: fable-5-1
The walk records a path as a regular file. If it is a FIFO (or a device node whose open blocks) by the time a hash worker opens it, `os.Open` blocks until a writer appears, which never happens. The worker never returns a result, so the phase waits forever, the lock stays held, and every later cron scan fails with `another scan is running`. The first SIGINT does not end it: `readRuns` returns, but the deferred `pool.stop()` waits for the blocked worker, so the hashed records still in the batch are never committed; only a second signal (uncaught, status 130) ends the process, leaving the database in WAL mode. The README says per-file errors never abort the run and that the first signal stops the scan cleanly.
Where (v1.0.0-rc1):
- https://git.eeqj.de/sneak/sfdupes/src/tag/v1.0.0-rc1/scan.go#L1335 and https://git.eeqj.de/sneak/sfdupes/src/tag/v1.0.0-rc1/scan.go#L1367 (blocking open; no check that the open file is still regular)
- https://git.eeqj.de/sneak/sfdupes/src/tag/v1.0.0-rc1/scan.go#L1257 (`stop` waits for every worker)
Reproduce: 302 same-size 9 MiB files, `scan --workers 1`; when the `hash:` line appears, `rm` the two files with the highest inode numbers and `mkfifo` them in their place. The bar stops at `[300/302]`; one thread sleeps in `wait_for_partner`; SIGINT prints nothing more; a second SIGINT ends it with status 130, an empty database and `-wal`/`-shm` files left behind.
**Definition of done**
- The hash and content phases open without blocking (`O_NONBLOCK` or equivalent) and check with `fstat` that the open file is regular; anything else is a per-path error: warned about, counted as skipped, no record written.
- A test that swaps a walked regular file for a FIFO before it is read fails before the fix (hangs until the test timeout) and passes after (one warning, exit 0).
Severity: minor. It needs a regular file replaced by a FIFO or blocking device between the walk and the read; the outcome is a scan that never ends and holds the lock until killed.
Model: fable-5-1
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The walk records a path as a regular file. If it is a FIFO (or a device node whose open blocks) by the time a hash worker opens it,
os.Openblocks until a writer appears, which never happens. The worker never returns a result, so the phase waits forever, the lock stays held, and every later cron scan fails withanother scan is running. The first SIGINT does not end it:readRunsreturns, but the deferredpool.stop()waits for the blocked worker, so the hashed records still in the batch are never committed; only a second signal (uncaught, status 130) ends the process, leaving the database in WAL mode. The README says per-file errors never abort the run and that the first signal stops the scan cleanly.Where (v1.0.0-rc1):
stopwaits for every worker)Reproduce: 302 same-size 9 MiB files,
scan --workers 1; when thehash:line appears,rmthe two files with the highest inode numbers andmkfifothem in their place. The bar stops at[300/302]; one thread sleeps inwait_for_partner; SIGINT prints nothing more; a second SIGINT ends it with status 130, an empty database and-wal/-shmfiles left behind.Definition of done
O_NONBLOCKor equivalent) and check withfstatthat the open file is regular; anything else is a per-path error: warned about, counted as skipped, no record written.Severity: minor. It needs a regular file replaced by a FIFO or blocking device between the walk and the read; the outcome is a scan that never ends and holds the lock until killed.
Model: fable-5-1