vcswatch reports that
this package seems to have new commits in its VCS but has
not yet updated debian/changelog. You should consider updating
the Debian changelog and uploading this new version into the archive.
Here are the relevant commit logs:
commit f4ee93c3f55e6f959cc755c546232d91aeaca0e0
Author: Xavier Roche <roche@httrack.com>
Date: Mon Sep 14 09:13:25 2026 +0200
Tests 436 and 459 give up when one write into their crawl directory is refused (#1675)
Three WSL2 jobs failed in `436_local-abort-lock` since 10 September, in
runs 34447609795, 34451707795 and 34487486427. Each was the only failing
test in its job, and all three report the same failure. A write of
`hts-abort.lock` into the crawl output directory was refused while that
directory was still there. The wait one line above had just read a file
inside it.
The review of PR #1631 dropped a retry here, because the evidence then
could not say whether anything had removed the directory. The walk added
by #1650 has now answered that. The helper retries for three seconds,
and reads the directory again after each failed write, so a removal is
named rather than waited out. It prints the try that landed on stderr,
which the Windows job uploads with the test log.
Test 258 covers three cases: the retry landing, the retry running out,
and a removal during the retries.
This is a mitigation and not a fix. Nothing here explains why drvfs
refuses a write into a directory it holds, and no upstream ticket is
filed. Two of the three jobs also show that the engine had ended its
mirror by the time of the failure. That is unexplained, and it belongs
on the issue.
Closes #1639
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 5f71d45c689138486a5db281ea786a8e6b48421d
Author: Xavier Roche <roche@httrack.com>
Date: Sun Sep 13 20:53:37 2026 +0200
httrack-android cannot see the -#c crash-test markers (#1673)
The two `-#c` markers went to stderr only. httrack-android recovers a
worker fault through coffeecatch, and it reads the engine's log callback
rather than stderr. So it cannot tell a deliberate crash test from a
real crash.
Both markers now also go to `hts_log_vprint(NULL, LOG_ERROR, ...)`. NULL
matters, because the callback runs before the `opt != NULL` guard. A
worker reaches the front end's log without touching opt, which is what
the recovery design needs. A front end that captures both channels sees
the marker twice.
`01_engine-crash-announce` checks stderr, then arms a real `-#c=dnssegv`
and faults, so both markers are checked on the path Android recovers.
Reverting either call site fails it.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 5108864f3d978f7a964c4520628b8ba91b9973cd
Author: Xavier Roche <roche@httrack.com>
Date: Sun Sep 13 20:36:41 2026 +0200
A WSL2 interop outage reads as failing tests on the Windows leg (#1674)
When WSL2's `init` cannot reach the Windows side it writes
`UtilAcceptVsock:235: accept4 failed 110` and `httrack.exe` never
launches. Whichever tests called it read empty output and reported it as
a content failure of their own. PR #1672 collected three unrelated reds
that way, and they looked like a buffer bug.
The driver now reads the failing tests' own logs for that line. When
every failure carries it, the leg ends on 3. That is the status a lost
worker already ends on, and it means repeat this leg rather than
investigate it. The failing tests are still named either way, so an
outage cannot hide a real red that picked the line up for another
reason.
Test 469 covers the verdict, test 337 the driver's gate.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 03d67612dc1c1ffc64d8ed7c6c6fb883b87e3191
Author: Xavier Roche <roche@httrack.com>
Date: Sat Sep 12 18:26:59 2026 +0200
-#c cannot fault a live worker, so the recovery path is unreachable (#1672)
`-#c=threadsegv` and `-#c=threadstack` cannot reach the engine's
fault-recovery path. The pre-pass runs the kind, then frees the option
set and returns −1 before any mirror starts. So there is no crawl
thread, and no engine worker to fault. A front end installs
`hts_set_thread_runner()` to recover a worker fault. Verifying #1671 on
a device took two hand-patched worker bodies for want of a way in.
`-#c=dnssegv` and `-#c=ftpsegv` arm a fault instead of taking one, and
the pre-pass lets the command line through so the mirror runs into it.
The resolver worker faults with its answer in hand and not yet
published. The FTP worker faults with its backlog slot already
registered. Those are the two states worth recovering from.
The option parser gains a `#c` case, because an armed kind now reaches
it.
Test 468 asserts what no other kind can: the project directory is on
disk when the fault lands, so the mirror was running. It resolves the
trace through addr2line to check the fault came from the worker's own
function, and it reads the signal by name. Its control is `-#c=segv`,
which leaves no project behind. Six mutants turn it red, one by arming
the control's own kind.
The httrack-android session asked for this, to replace its patches.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit a9bdf1c8ad6b0b9287cc09dc3c98fbe2cbbc3972
Author: Xavier Roche <roche@httrack.com>
Date: Sat Sep 12 13:07:29 2026 +0200
The crawl waits forever for an FTP worker a crash recovery cut short (#1671)
A crawl could hang forever at teardown. `back_launch_ftp()` took its
worker off the live-worker list on its last line. `ftp_stop_workers()`
polls for an empty list with no bound, so a worker that never reached
that line wedged the crawl thread.
A worker reaches it unless something cut its body short, which is what a
front end's thread runner does. httrack-android now installs one through
coffeecatch, to catch a crash signal on an engine worker and recover
from it instead of dying.
The thread layer now runs a tail callback once the body is over, whether
or not the body got there. FTP hands its slot back from that tail, and
the DNS resolver releases its job there.
A worker is not resumable after a crash, so the mirror ends rather than
failing the one link. The thread layer raises a flag, and the crawl
thread turns it into `HTS_EXIT_MIRROR_ABORTED`, being the only thread
that may touch `opt`. A worker carries the round it was spawned in, so
one an earlier mirror abandoned cannot abort this one.
Three selftests and seventeen mutants cover it. Two older paths dropped
that exit status on the way out, and one of them also swallowed the
cache-write abort.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 0ae7bcdb5e9f11281ccaee86973c84444d8fd442
Author: Xavier Roche <roche@httrack.com>
Date: Fri Sep 11 19:38:49 2026 +0200
Test 250 reads an exited process as still running on GNU/Hurd (#1668)
3.50.2-1 failed to build on hurd-amd64 and hurd-i386, and
`250_timeout-poll-nofork` was the only failure on both. 3.50.1-1 built,
so this is a regression from #1554, which added `pid_is_zombie`.
Neither of that helper's two routes works on GNU/Hurd. Its procfs builds
`/proc/PID/stat` out of Mach data an exited process no longer has, so
the read fails where Linux answers `Z`. The fallback `ps -o state= -p
PID` fails too, because Hurd's `ps` rejects `-p` and takes the pid
positionally. `kill -0` then keeps succeeding on the zombie until the
grace runs out.
The fix is the second of those. Hurd's `ps` does know the state, from
proc-info, which a zombie still carries, so `pid_state` now tries both
spellings and takes whatever the host says.
Four earlier drafts of this branch tried instead to read the failure
itself as proof of death, and review broke each one. The last one shows
why none of them could work. `/proc/PID/stat` needs `PSTAT_THREAD_WAIT`,
libps sets that only while the message port is usable, and
`should_suppress_msgport` turns it off for a suspended task. A live
process that is merely stopped reads EIO on Hurd, so no test on the file
can tell it from a dead one.
`pid_state_readable` rests on the same answer, which is what it always
claimed to report. A host neither route answers for now makes the test
skip rather than assert. The guard also runs after the kill now, because
asking about a live process is how the state Hurd cannot report came to
be graded.
One fix here is older than the branch. Linux writes `comm` into
`/proc/PID/stat` unescaped. A process named `") Z<LF>q"` therefore
splits the file, and the first line ends in a state it is not in.
Reading one line reported `Z` for a sleeping process.
`pid_state` takes one row from `ps` or none. A header, or an answer
covering several pids, says nothing about this one, and folding the rows
together invents a state no column held.
Fourteen mutants of the helper each fail a test, one of them a stderr
leak an earlier draft left behind.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 45e28c1876ecfeab23bb5209a59986b128a2e5e8
Author: Xavier Roche <roche@httrack.com>
Date: Fri Sep 11 16:44:02 2026 +0200
A Windows job whose runner vanishes needs a human to re-run it (#1669)
A `windows-build` job killed the way #1228 describes fails with no
failed step, no log and no artifact, so only a re-run clears it. Since
#1585 that is about one job a fortnight rather than one in eight, so
this covers the residual, not the old rate.
`tools/windows-kill-grade.sh` decides, and refuses anything ambiguous.
It collects every job that did not succeed and is not still running. All
of them must be plain failures, each with no named step and an
unfinished one, or no steps at all. Test 466 pins that with ten mutants,
each killed by a case it does not share.
The step re-reads `run_attempt` from the run rather than from the event,
and allows exactly one re-run. A superseded run is left alone, because
windows-build cancels in-progress runs of the same ref, so re-running
the old one would cancel the new one. A push landing between that check
and the POST still races it.
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit e61d483d412d1bca3513bd5dd12027ef7395e23f
Author: Xavier Roche <roche@httrack.com>
Date: Fri Sep 11 15:29:43 2026 +0200
windows-build.yml does not record that the MSYS suite leg was killing the runner (#1667)
The MSYS test-suite leg was killing the hosted runner. Removing it in
#1585 took the Windows runner-death rate from 12.5% to 0.3% over 1515
jobs. `windows-build.yml` records only that MSYS wedged, so nothing
there warns the next person off adding a leg back. The measurement is on
#1228.
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 600adfd0d06d4c6cf4732f71f25b82ed62b135eb
Author: Xavier Roche <roche@httrack.com>
Date: Fri Sep 11 14:05:40 2026 +0200
Nothing tells a translator to be a native reader, or which files a new language needs (#1665)
Two gaps in `lang/README.md`, both found while answering a forum request
for a Thai translation.
It never states the rule that matters most. Only a native reader should
send a translation, and never machine or LLM output, because nobody here
can check one.
Its "Adding or updating a language" section is written for updating a
catalog that already exists. Follow it for a new language and the PR
fails tests 62, 225 and 373. Nothing told the contributor about
`lang.def`, `lang.indexes`, the two per-catalog pins under `tests/`,
`install-manifest.txt`, or the credits roster.
So the section is split by role. A translator sends one file, and the
maintainer steps move under their own heading.
Checked by staging a 31st catalog and running the full suite. That
turned up two traps, now written down. `lang.indexes` wants the ISO code
lowercased, and `373_credits.test` needs a `LABEL` row when
`LANGUAGE_WINDOWSID` is not the English name.
---------
Signed-off-by: Xavier Roche <xroche@gmail.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit b276d1bb83bc21c6bed3ddca8bf59b4f716635c8
Author: Xavier Roche <roche@httrack.com>
Date: Fri Sep 11 10:48:26 2026 +0200
hts_set_thread_runner() is exported but no installed header declares it (#1664)
The 3.50-2 release notes tell embedders about three calls, and
`hts_set_thread_runner()` was not reachable. The symbol is exported, but
its only declaration sat in `src/htsthread.h`, which no install carries,
so a caller had to write the prototype by hand.
The declaration now lives in `src/httrack-library.h`, which is
installed. Installing `htsthread.h` would drag `htswin32.h` in with it,
and installing `htstools.h` would publish internal link types. The
`hts_find*` family was already declared in both headers. This drops the
copy in `htstools.h` and lets that header include the public one. No
exported symbol is added or removed, so `VERSION_INFO` does not move.
The new test compiles and links a consumer against the installed headers
alone. Without the change it fails with `error: unknown type name
'hts_thread_runner'`. `html/library.html` needs no edit, because the
installed header list is unchanged.
Closes #1663
---------
Signed-off-by: Xavier Roche <roche@httrack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>