Affected version(s)
Contao 4.7.1, PHP 7.2.11
Description
Ich bin's mal wieder mit einem weiteren Internal Server Error (Failed to acquire the "default" lock.) beim Erstellen der Symlinks aus dem Backend heraus. Das Kuriose: ich habe gestern drei Seiten auf demselben Server von 4.7.0 auf 4.7.1 aktualisiert (via Contao-Manager) und nur eine davon hat das Problem. Aus meiner Sicht sind alle Installationen exakt gleich.
Log
[2019-02-22 10:59:16] request.INFO: Matched route "contao_backend". {"route":"contao_backend","route_parameters":{"_route":"contao_backend","_scope":"backend","_token_check":true,"_controller":"Contao\\CoreBundle\\Controller\\BackendController::mainAction"},"request_uri":"https://********.de/contao?do=maintenance&ref=FWrXkhuq","method":"POST"} []
[2019-02-22 10:59:16] lock.NOTICE: Failed to acquire the "default" lock. {"resource":"[object] (Symfony\\Component\\Lock\\Key: default)","exception":"[object] (Symfony\\Component\\Lock\\Exception\\LockStorageException(code: 0): fopen(/tmp/sf.default.N6juwc4.lock): failed to open stream: Permission denied at /***/***.de/vendor/symfony/lock/Store/FlockStore.php:93)"} []
[2019-02-22 10:59:16] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Lock\Exception\LockAcquiringException: "Failed to acquire the "default" lock." at /***/***.de/vendor/symfony/lock/Lock.php line 101 {"exception":"[object] (Symfony\\Component\\Lock\\Exception\\LockAcquiringException(code: 0): Failed to acquire the \"default\" lock. at /***/***.de/vendor/symfony/lock/Lock.php:101, Symfony\\Component\\Lock\\Exception\\LockStorageException(code: 0): fopen(/tmp/sf.default.N6juwc4.lock): failed to open stream: Permission denied at /***/***.de/vendor/symfony/lock/Store/FlockStore.php:93)"} []
How to reproduce
Contao-Backend -> Systemwartung -> Symlinks neu erstellen
Laut Fehlermeldung bestehen keine Schreibrechte auf dein /tmp Directory.
Hat aber 750. Genau wie das der anderen beiden Installationen. Selbst mit 777 ändert das nichts an der Fehlermeldung.
Existiert die Datei /tmp/sf.default.N6juwc4.lock?
Nein. Du meinst aber schon /system/tmp, richtig?
Nein. Du meinst aber schon /system/tmp, richtig?
Nein, /tmp.
Ok. /tmp hat 773 und beinhaltet die o.g. Datei nicht. Ich denke, dass das nicht der Knackpunkt sein kann, da auf demselben Server (DomainFactory Managed Server) zwei andere Contao 4.7.1-Installationen (die logischerweise auch in /tmp speichern) problemlos funktionieren und hier der Fehler nicht auftritt.
Fehlkonfiguration beim Hoster. sys_get_temp_dir() muss den Pfad zu einem temporären Verzeichnis zurückgeben, das durch PHP-Applikationen beschreibbar ist.
sys_get_temp_dir() gibt korrekt /tmp zurück.
Ja, aber dein User hat keine Rechte da drauf. Sprich, falsch konfiguriert.
Hm, wie erklärt sich dann, dass zwei andere Installationen auf demselben Server die Symlinks problemlos erstellen können?
Das kann ich dir nicht sagen, das musst du den Hoster fragen :)
Danke für euren Input. Ich frage beim Hoster parallel an.
Ich verstehe es aber trotzdem nicht, weil das Verzeichnis /tmp hat für alle Gruppen und Nutzer auf dem Server Lese- und Schreibrechte. Das ist auch eine ganz normale Kiste bei DomainFactory. Bisher gab es da mit Lese-/Schreibrechten noch nie irgendwelche Probleme.
Aus mir unbekannten Gründen funktioniert es nun. Sollte ich von der DF-Technik noch Info bekommen, ob und was sie verändert haben, poste ich das hier noch mal.
Danke für eure Hilfe und sorry für das zweite Issue zu dem Thema, das letztendlich erneut server-seitig war.
Das Problem besteht bei DF leider immer mal wieder. Erst wenn die Dateien im tmp-Verzeichnis älter als 3 Tage sind, werden sie gelöscht. Danach funktioniert das Schreiben der Symlinks wieder.
Eine mögliche Lösung seitens Contao könnte sein, den Hash der Datei (hier sf.default.N6juwc4.lock) bei jedem Aufruf anders zu gestalten. Dann würde Contao nicht versuchen dieselbe Datei wie zuvor zu lesen, sondern jedes Mal eine neue erzeugen.
Siehe auch:
contao/contao-manager#136
https://www.df.eu/de/support/df-faq/webhosting/skriptsprachen/php/#c1408
Das Problem ist wohl, dass die .lock-Datei immer denselben Namen hat, egal welcher Benutzer sie anlegt. Wir haben auf dem dedizierten Managed Server bei DF mehrere Nutzer mit unterschiedlichen Quotas. Natürlich kann Nutzer A dann nicht die tmp-Dateien des Nutzers B lesen.
Gut, wenn die Userberechtigungen stimmen, dann passt das. Ich sehe den Use Case jetzt und wir sollten was dagegen unternehmen. @contao/developers ggf. up4discussion.
Das Problem ist wohl, dass die .lock-Datei immer denselben Namen hat, egal welcher Benutzer sie anlegt. Wir haben auf dem dedizierten Managed Server bei DF mehrere Nutzer mit unterschiedlichen Quotas. Natürlich kann Nutzer A dann nicht die tmp-Dateien des Nutzers B lesen.
Hm, sollte in so einem Setup nicht jeder Nutzer sein eigenes Temp Verzeichnis bekommen? Siehe auch https://github.com/contao/contao/issues/267#issuecomment-453941709
Nein, wenn die User so konfiguriert sind, dass sie die Files der anderen User nicht lesen können, ist ja alles gut. Es wäre nur problematisch, wenn dem nicht so wäre 😄
True - aber dann ist es immer noch seltsam, dass verschiedene User die selbe Lock Datei benutzen wollen - das sollte ja nicht möglich sein.
Wir nutzen ja den Lock von Symfony - ich frage mich warum der das so macht …
Ja, so funktioniert einfach die Symfony Lock Framework-Integration. Du kannst mehrere "Lock Resources" angeben, standardmässig ist es einfach eine. Die nennt sich default und zeigt auf den SemaphoreStore wenn supported, ansonsten Fallback auf FlockStore wie im Beispiel hier.
Und die Stores generieren den Lock auf Basis des Resource-Namens, also default.
Beweis: FlockStore macht strtr(substr(base64_encode(hash('sha256', $key, true)), 0, 7), '/', '_') und wenn man $key auf 'default' setzt, ergibt das N6juwc4 und siehe da, das stimmt mit der Fehlermeldung überein 😄 .
Sprich für jede Installation auf jedem Server wird es immer das gleiche File sein, so dass sich mehrere Symfony-Installationen immer konkurrenzieren werden.
Also locken bedeutet im Moment, ein Locking jeglicher Symfony Applikationen die auf die gleiche Resource zugreifen (bei Flock = identisches tmp dir, bei Redis = identische Redis-Instanz etc.).
Ich muss wohl mal ein Issue bei Symfony eröffnen, aber wohl nicht heute.
Ich muss wohl mal ein Issue bei Symfony eröffnen
Das sehe ich genauso.
Übrigens hatten wir schon mal ähnliche Probleme: https://github.com/contao/core-bundle/issues/1551
@Toflar früher hatte Contao das selbst gesetzt:
Seit der Umstellung auf SemaphoreStore wird das nicht mehr gemacht. Ein Symfony Problem ist das imho nicht.
Du meinst Umstellung auf die Symfony Lock Komponente. Mit Semaphore hat das nichts zu tun.
in Symfony Problem ist das imho nicht.
Doch. Weil es betrifft jede Symfony Applikation, nicht nur Contao.
Du meinst Umstellung auf die Symfony Lock Komponente. Mit Semaphore hat das nichts zu tun.
Genau, ja.
Doch. Weil es betrifft jede Symfony Applikation, nicht nur Contao.
Ja - ich meine nur ob Symfony die Verwendung des FlockStore in dieser Form überhaupt vorsieht, ohne eben selbst den Pfad oder Namen zu setzen.
Du setzt nie einen Pfad. Es gibt je nach Store keinen Pfad. Du setzt einen Key und das FrameworkBundle selber setzt einen namens default. Und wenn 10 Systeme so konfiguriert sind, dass sie am gleichen Ort locken (das hat nichts mit dem Store zu tun, das kann bei jedem Store passieren), dann lockst du applikationsübergreifend. Das würde auch passieren, wenn wir nicht default sondern foobar nehmen würden. Wir müssten explizit was nehmen, was die Installation identifiziert und ich denke das sollte Symfony selber auch, deswegen werd ich erst dort mal ein Issue aufmachen und sehen was deren Meinung ist. Wenn sie sagen, dass wollen sie so, dann können wir es immer noch für uns lösen.
Wie am 11. April auf Mumble besprochen, ist das Locking für die Commands nicht notwendig und kann entfernt werden. Dadurch löst sich auch dieses Problem. 😄
Behoben in a84e341de23d351c8d8e4975a2bad8d4750bf640.
Sollten wir das "locked command" noch deprecaten?
Sorry, dass ich hier noch mal schreibe. Wir sind gerade an dem Punkt und ich bin nun über
Leo: "Wie am 11. April auf Mumble besprochen, ist das Locking für die Commands nicht notwendig und kann entfernt werden. Dadurch löst sich auch dieses Problem."
gestolpert. Heißt das, in Contao 4.9 bspw. kann ich ein und denselben Command mehrfach parallel ausführen? Also auch die Contao Core Commands? Bedeutet (konstruiertes Beispiel ^^): wenn ich bspw. contao:symlinks als minütlichen Cron ausführe und das rein theoretisch mehr als 1 Minute dauern würde, kommen sich beide Commands ins Gehege?
So, wie ich es verstanden habe, muss man jetzt in den Komponenten selbst für den Lock sorgen?
Danke für die Aufklärung und habt ein schönes Wochenende! ;)
Most helpful comment
Wie am 11. April auf Mumble besprochen, ist das Locking für die Commands nicht notwendig und kann entfernt werden. Dadurch löst sich auch dieses Problem. 😄