separate desktop and server source recovery namespaces
- Dominant language
- Java
- Stars
- 5.1k
- Forks
- 1.2k
- PR merge metrics
- PR metrics pending
Description
Desktop and Server should have separate source-document recovery namespaces when they run as the same user and share an RStudio data directory. Switching between the two is uncommon in normal use, but it must preserve unsaved work and must not disrupt a running session. Development builds and automated tests make this overlap more likely.
This is an architectural follow-up to #18744 and the immediate mitigation in #18745. It records the investigation and proposed direction; the namespace change has not been implemented.
The failure was reproduced on macOS with two no-project `rsession` processes sharing a temporary `RSTUDIO_DATA_HOME`: a Desktop-mode session renamed a live Server-mode session's `sources/session-` directory during orphan recovery. The Server process remained alive, but a subsequent actual `new_document` RPC failed with ENOENT when writing `-contents`. Existing unsaved documents moved with the directory. Giving the processes separate data directories prevented the failure. See #18744 for reproduction steps. This establishes a failure mechanism consistent with the reported symptoms; it does not establish which competing process caused the original incident.
The underlying problem is that recovery treats a shared directory as a common ownership domain, while processes can interpret its locks differently. Desktop defaults to advisory locking and Server to link-based locking on Unix; configuration can override the choice. Windows uses advisory locking. Previously, orphan recovery only inspected the current process's selected lock type. #18745 checks both types, rejects known ownership conflicts, and isolates C++ session test data/configuration. Its targeted tests cover live coexistence, abandoned-document recovery, and competing sessions with the same ID. This is a compatibility mitigation: older binaries retain the original behavior, and the ownership check, directory rename, and lock acquisition remain separate operations rather than an atomic ownership transfer.
Code inspection at [4608e7c](https://github.com/rstudio/rstudio/tree/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d) found a contained starting point:
- With no project, [scopedScratchPath() uses the common user scratch directory](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/SessionModuleContext.cpp#L1218-L1224). Source recovery consequently shares the `sources` root across modes.
- [The supervisor constructs the recovery paths](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/SessionSourceDatabaseSupervisor.cpp#L53-L114): live `session-*` directories, persistent titled/untitled documents in `per/t` and `per/u`, and most-recent stores `mt` and `mu`. [Document properties use another direct `sources/prop` path](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/SessionSourceDatabase.cpp#L102-L109). These should use a common namespace-aware root.
- Project scratch directories already [include a context ID](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/projects/SessionProjectContext.cpp#L217-L226). Desktop and Server [store state separately, explicitly to avoid sharing source databases](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/prefs/UserStateLayer.cpp#L38-L43), so normal project configurations already have some separation. Copied profiles and legacy context IDs still need consideration.
- Most document operations already obtain their directory through the source database API. A focused root change appears to require only a handful of production files; no frontend or document-format change is expected. Migration and regression coverage are the larger part of the work.
A possible layout is:
```text
sources/
desktop/
session-/
per/{t,u}/
mt/
mu/
prop/
server/
session-/
per/{t,u}/
mt/
mu/
prop/
```
The precise namespace key remains a design decision: an explicit mode component guarantees Desktop/Server separation, while a stable context/profile component could also distinguish independent installations. It must remain stable across restarts, and Server's existing multi-session subdirectories and intended recovery behavior must be preserved. A per-process namespace alone would prevent subsequent recovery from finding abandoned work.
Alternatives and scope:
- **Separate source recovery roots:** directly prevents cross-mode recovery from claiming the other mode's documents, independent of lock configuration. Same-mode concurrency still requires correct locking; tests still need isolated state.
- **Separate the entire Desktop/Server data directory:** provides broader isolation, but affects substantially more state and migration behavior. It is not necessary to move preferences or all runtime state to address this source database problem. Active-session storage can also [involve Server RPCs](https://github.com/rstudio/rstudio/blob/4608e7ceb59a14ecdf94cca4f3bf3dddf92e737d/src/cpp/session/SessionActiveSessionsStorage.cpp#L39-L61), so it warrants a separate audit.
- **Use one default lock type:** reduces default mismatches but does not establish a shared protocol when users customize locking or run older versions. Intentionally shared stores need an agreed ownership protocol, including atomic claims and safe protocol transitions, rather than relying on matching process defaults.
Migration needs an explicit design. Legacy `sources/session-*` and persistent stores do not reliably identify which mode should inherit the documents. A blind move or recursive copy can interfere with a live older session or allow concurrent launches to import the same recovery state. Existing `sdb` and `source_database_v2` migrations also need review. The old orphan scanner only considers immediate `session-*` children of `sources`, so it would ignore the proposed mode subdirectories; that helps coexistence but is not a complete upgrade/downgrade strategy. We should prioritize preserving and making unsaved work recoverable when switching modes, with the treatment of legacy shared tabs documented explicitly.
Acceptance and regression coverage should include:
- Concurrent Desktop/Server launches in both orders, with no project, sharing a temporary data root: each retains its directory and can create/save documents regardless of supported lock configuration.
- Same-mode restart, normal exit restoration, crash recovery, and Server suspend/resume and multi-session behavior.
- Existing project isolation, including legacy or copied context state.
- Migration of titled and untitled unsaved documents, simultaneous first launches, interrupted migration, and coexistence with an older running binary. No live directory may be reclaimed, and legacy work must remain recoverable.
- Explicit behavior after a mode switch or downgrade, without silently deleting or making recovery data inaccessible.
- Preservation of `RSTUDIO_DATA_HOME` overrides and automated-test isolation; platform coverage including Windows.
Historical context: #6742 documented shared Desktop/Server source databases for projects and was closed after a fix; #10242 documented a separate Desktop/Server source database interaction affecting session restarts and was also closed. These show prior issues in this area, but the newly reproduced no-project failure is tracked in #18744.
Contributor guide
Research direction
Start with scopedScratchPath() in src/cpp/session/SessionModuleContext.cpp, then trace recovery paths in SessionSourceDatabaseSupervisor.cpp and the sources/prop path in SessionSourceDatabase.cpp. Review SessionProjectContext.cpp and UserStateLayer.cpp for existing context separation, then inspect the migration and regression tests mentioned in the issue. Done means stable Desktop/Server namespaces, preserved recovery and migration behavior, and coverage for concurrency, restarts, legacy data, and Windows.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend, desktop
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100