docs: KONZEPT-WINDOWS — Rippy v5 als eigenstaendiges Electron-Programm
Die heutige Windows-Fassung ist der Docker-Code in einer EXE: PyInstaller
buendelt docker/api und docker/worker, uvicorn laeuft auf 127.0.0.1:7788,
pywebview stellt ein Fenster davor. Elf Release-Kandidaten in drei Tagen,
und die Funde sind fast alle derselbe Typ — Linux-Annahmen, die unter
Windows etwas anderes bedeuten (timeout ls -d, shutil.which, /app,
/dev/{name}, F: ohne Trenner).
Das Konzept beschreibt den Neubau als Windows-Programm: Electron 44,
TypeScript durchgehend, Einzelplatz, kein Python, kein HTTP-Server.
Vier Entscheide des Commanders (30.08.2026) sind eingearbeitet:
alles TypeScript/Node · Docker bleibt unangetastet · reiner Einzelplatz ·
eigener Branch.
Vor der ersten Zeile Konzept gemessen (Regel D), Belege in beweise/:
* Win32 aus Node an G: (HL-DT-ST BD-RE BU40N) — Laufwerkssuche,
CreateFileW, QUERY_PROPERTY (Modell + Serial), CHECK_VERIFY2,
GET_LENGTH_INFO (33,76 GB -> Blu-ray). IOCTL_CDROM_DISK_TYPE
antwortet mit Fehler 50 — derselbe Befund wie im Python-Treiber.
* Prozess-Leine (Job Object): Kind stirbt mit dem per taskkill /F
ohne /T abgeschossenen Elternprozess. Die Messung aus rc10, in
Node nachgestellt.
* node:sqlite ist in Node 24 eingebaut — in Electron noch ungeprueft,
ausdruecklich als offener Punkt markiert.
Akutestes Risiko im Dokument: MakeMKVs freier Beta-Key laeuft Ende
September 2026 ab, die Kaufseite fuer die Dauerlizenz ist seit Mai defekt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9050fea3f0
commit
cb811bec28
@@ -0,0 +1,50 @@
|
||||
// Beweis-Test 2: Kann Node eine Windows-Arbeitsgruppe (Job Object) setzen,
|
||||
// die Kindprozesse mitreisst, wenn der Elternprozess HART beendet wird?
|
||||
// Das ist der Mechanismus aus SAVEPOINT v4.0-rc10 — ohne ihn ueberlebt
|
||||
// makemkvcon Rippy und haelt das Laufwerk fest.
|
||||
const koffi = require('koffi');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
const kernel32 = koffi.load('kernel32.dll');
|
||||
const CreateJobObjectW = kernel32.func('void* __stdcall CreateJobObjectW(void *lpJobAttributes, str16 lpName)');
|
||||
const SetInformationJobObject = kernel32.func('bool __stdcall SetInformationJobObject(void *hJob, int JobObjectInformationClass, void *lpJobObjectInformation, uint32_t cbJobObjectInformationLength)');
|
||||
const AssignProcessToJobObject = kernel32.func('bool __stdcall AssignProcessToJobObject(void *hJob, void *hProcess)');
|
||||
const GetCurrentProcess = kernel32.func('void* __stdcall GetCurrentProcess()');
|
||||
const GetLastError = kernel32.func('uint32_t __stdcall GetLastError()');
|
||||
|
||||
// JobObjectExtendedLimitInformation = 9 (winnt.h)
|
||||
const JobObjectExtendedLimitInformation = 9;
|
||||
// JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000 (winnt.h)
|
||||
const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;
|
||||
|
||||
const job = CreateJobObjectW(null, null);
|
||||
if (koffi.address(job) === 0n) {
|
||||
console.log('CreateJobObjectW fehlgeschlagen, Win32-Fehler', GetLastError());
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('1. CreateJobObjectW -> Arbeitsgruppe angelegt');
|
||||
|
||||
// JOBOBJECT_EXTENDED_LIMIT_INFORMATION ist 144 Byte auf x64.
|
||||
// LimitFlags liegt im eingebetteten BASIC_LIMIT_INFORMATION bei Offset 16.
|
||||
const info = Buffer.alloc(144);
|
||||
info.writeUInt32LE(JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, 16);
|
||||
if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, info, 144)) {
|
||||
console.log('SetInformationJobObject fehlgeschlagen, Win32-Fehler', GetLastError());
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('2. SetInformationJobObject -> KILL_ON_JOB_CLOSE gesetzt');
|
||||
|
||||
if (!AssignProcessToJobObject(job, GetCurrentProcess())) {
|
||||
console.log('AssignProcessToJobObject fehlgeschlagen, Win32-Fehler', GetLastError());
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('3. AssignProcessToJobObject -> dieser Prozess haengt in der Gruppe');
|
||||
|
||||
// Ein langlebiges Kind starten — der Platzhalter fuer makemkvcon.
|
||||
const kind = spawn('ping', ['-n', '300', '127.0.0.1'], { stdio: 'ignore' });
|
||||
console.log('4. Kindprozess gestartet, PID ' + kind.pid);
|
||||
console.log('ELTERN-PID=' + process.pid);
|
||||
console.log('KIND-PID=' + kind.pid);
|
||||
|
||||
// Offen halten, bis uns jemand hart abschiesst.
|
||||
setTimeout(() => { console.log('Zeit abgelaufen'); process.exit(0); }, 60000);
|
||||
Reference in New Issue
Block a user