Skip to content

userTransfer: post-transfer rTorrent restart ignores the .rtorrentDisable per-user opt-out marker #869

Description

@MagnaCapax

Origin: Customer support ticket. Suggested Fix reflects ticket agent
investigation — do not derive fix from title or symptom alone.

Summary

userTransfer.php's post-transfer convergence starts rTorrent unconditionally. It never consults the .rtorrentDisable per-user opt-out marker, so a user who has explicitly opted out of rTorrent has it started for them the moment their migration completes.

Symptom

A user opts out of rTorrent (~/.rtorrentDisable present — the GH#470 per-user opt-out that checkRtorrent.php honours). Their account is then migrated to another host with userTransfer.php. At the end of the transfer rTorrent starts on the target, loads the migrated session and begins announcing. It is stopped again on the next checkRtorrent.php tick, so the window is bounded by the cron interval (currently */2), but the client does start and does announce.

Where the source account is still live and seeding the same torrents — the normal state during a staged migration — both hosts announce the same torrents for that window.

Root Cause

scripts/lib/userTransfer/postSetup.php:

  • pmssUserTransferPostSetup() calls pmssUserTransferRequestRtorrentRestart($home, $localUser) unconditionally (~line 44).
  • pmssUserTransferRequestRtorrentRestart() touches www/.rtorrentRestart, then pmssUserTransferRunRtorrentRestart() executes ~/.rtorrentRestart.php immediately ("so migration is not cron-latent").
  • etc/skel/.rtorrentRestart.php gates only on file_exists('www/.rtorrentRestart'). There is no .rtorrentDisable check anywhere on that path.

scripts/cron/checkRtorrent.php (~line 123-129) DOES honour the marker — "stop and stay stopped" — which is why the state self-corrects rather than persisting. So the opt-out contract is enforced in one code path and ignored in another: the same condition, two rules, guaranteed to drift.

Reproduction

  1. Create ~/.rtorrentDisable for a test user; confirm checkRtorrent.php keeps rTorrent stopped.
  2. On a target host run php /scripts/util/userTransfer.php <user> <user> <source-host> for that user.
  3. When the transfer converges, observe rTorrent running on the target despite the marker.
  4. Wait one checkRtorrent.php tick — it is stopped again.

Environment

PMSS git/main, Debian 12 (bookworm). The code path is suite-independent.

Suggested Fix

Guard the restart request on the same predicate checkRtorrent.php already uses, at the top of pmssUserTransferRequestRtorrentRestart():

if (is_file($home.'/.rtorrentDisable')) {
    logMessage('[INFO] Skipping rTorrent restart (user opt-out marker .rtorrentDisable present)');
    return;
}

so neither the marker file nor the immediate execution happens.

Preferred variant: extract the predicate into one shared helper (e.g. pmssRtorrentUserOptedOut(string $home): bool) called from BOTH checkRtorrent.php and postSetup.php, so the opt-out contract lives in a single place and cannot drift again. The inline check is the minimal fix; the shared predicate is the correct one.

Related but distinct: #717 (.rtorrentRestart.php comm matching) and #836 (checkRtorrent.php killall comm matching) concern how the restart/stop identifies the process. This issue is about the restart being requested at all.

(The cron stops it two minutes later; it should never have started.)


Tier-3 declared at filing: --why public-surface — GH#631 tier gate. Declared fix size: 25 lines vs 52-line body — size gate (operator directive 2026-07-29).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcustomer-reportedIssue originated from customer ticket - extra scrutiny required

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions