fix(auswurf): CDROMEJECT meldete Erfolg und tat nichts - erst entriegeln
Ampel / ampel (push) Successful in 29s

Commander-Meldung: "Den Button gibt es in den Settings, aber es passiert nicht,
das Laufwerk geht nicht auf." Am laufenden System nachgestellt, mit der Disc, die
gerade drin lag:

  wirf_disc_aus("/dev/sr0")      -> True
  CDROM_DRIVE_STATUS danach      -> 4 (Disc drin)

Das ioctl wird also ANGENOMMEN und tut nichts. Ursache: MakeMKV verriegelt
waehrend des Rips die Laufwerkstuer (CDROM_LOCKDOOR 1) und entriegelt sie nicht
wieder. Ein verriegeltes Laufwerk quittiert den Auswurf trotzdem mit Erfolg.
Gegenprobe an derselben Disc:

  CDROM_LOCKDOOR 0 + CDROMEJECT  -> Status 2 (SCHUBLADE OFFEN)

Genau das macht das Werkzeug `eject` immer: erst entriegeln, dann auswerfen.

Zweite Haelfte des Fixes, und die wichtigere: Das Ergebnis wird GEPRUEFT statt
geglaubt. Bisher gab wirf_disc_aus True zurueck, sobald das ioctl nicht geworfen
hatte - und ins Log kam "Disc ausgeworfen", waehrend die Schublade zu blieb.
Deshalb ist der Fehler in v3.14 durchgerutscht: Dort wurde richtig festgestellt,
dass die Einstellung von niemandem gelesen wurde, und danach WURDE sie gelesen -
ausgeworfen wurde weiterhin nicht. Jetzt wird das Laufwerk gefragt (bis zu 5 s,
die Schublade braucht ein bis zwei), und "kein Datentraeger" zaehlt mit, weil ein
Slot-Laufwerk keine Schublade hat.

Dieselbe Luecke steckte im Auswurf-Knopf der API (devices.eject) - dort mit
Klartext-Fehler, wenn die Disc drin bleibt.

Der Auswurf sitzt uebrigens schon an der richtigen Stelle: nach dem Rip, VOR dem
Einreihen der Kompression. Und das Laufwerk ist waehrend `transcoding` frei -
has_active_job blockiert nur bei pending/running, der Worker laeuft mit 4 Slots.
Die zweite Disc parallel war also nur am nicht aufgehenden Laufwerk gescheitert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-07-26 14:03:10 +02:00
parent 2587fe63af
commit be04a9772e
3 changed files with 210 additions and 17 deletions
+35 -1
View File
@@ -20,13 +20,47 @@ from detection import (
# include/uapi/linux/cdrom.h
CDROMEJECT = 0x5309
CDROM_LOCKDOOR = 0x5329 # 1 = Tür verriegeln, 0 = entriegeln
CDROM_DRIVE_STATUS = 0x5326
CDS_NO_DISC = 1
CDS_TRAY_OPEN = 2
AUSWURF_WARTEN_SEKUNDEN = 5
def eject(device_path: str) -> None:
"""Wirft die Disc aus (CDROMEJECT-ioctl). Wirft OSError bei Fehlern."""
"""Wirft die Disc aus und prüft es nach. Wirft OSError, wenn sie drin bleibt.
⚠️ ERST ENTRIEGELN (Befund 26.07.2026, am laufenden System gemessen): Ein
nacktes CDROMEJECT wird von einem verriegelten Laufwerk mit ERFOLG quittiert
und tut nichts. MakeMKV verriegelt die Tür während des Rips
(`CDROM_LOCKDOOR 1`) und entriegelt sie nicht wieder — danach blieb die
Schublade zu, während Rippy „Disc ausgeworfen" ins Log schrieb. Gegenprobe
an derselben Disc: mit `CDROM_LOCKDOOR 0` davor geht sie auf (Status 2).
Deshalb macht das Werkzeug `eject` immer beides.
Gleichlautend in worker/ripping.wirf_disc_aus — es gibt kein geteiltes Paket
zwischen den Containern; dort steht die ausführliche Herleitung.
"""
import time
fd = os.open(device_path, os.O_RDONLY | os.O_NONBLOCK)
try:
try:
ioctl(fd, CDROM_LOCKDOOR, 0)
except OSError:
pass # nicht verriegelt oder ioctl unbekannt — Auswurf trotzdem versuchen
ioctl(fd, CDROMEJECT, 0)
# Nachsehen statt hoffen. „Kein Datenträger" zählt mit: ein
# Slot-Laufwerk hat keine Schublade.
for _ in range(AUSWURF_WARTEN_SEKUNDEN):
if ioctl(fd, CDROM_DRIVE_STATUS, 0) in (CDS_TRAY_OPEN, CDS_NO_DISC):
return
time.sleep(1)
raise OSError(
"Das Laufwerk hat den Auswurf angenommen, die Disc ist aber noch "
"drin. Blockiert etwas die Schublade, oder läuft noch ein Zugriff?"
)
finally:
os.close(fd)