Heim  >  Artikel  >  Backend-Entwicklung  >  Warum schlägt „setns“ mit EINVAL in einer Go-Multithread-Umgebung fehl?

Warum schlägt „setns“ mit EINVAL in einer Go-Multithread-Umgebung fehl?

Linda Hamilton
Linda HamiltonOriginal
2024-11-01 09:23:30653Durchsuche

Why Does 'setns' Fail with EINVAL in a Go Multithreaded Environment?

Aufruf von „setns“ von Go aus schlägt mit EINVAL für MNT-Namespace fehl

Problem

Beim Versuch, „setns“ von Go aus aufzurufen, um den MNT einzugeben Namespace gibt der Aufruf konsistent EINVAL zurück. Dieses Problem wird beobachtet, obwohl eine C-Implementierung derselben Funktionalität ordnungsgemäß funktioniert.

Ursache

Das Problem rührt von der Tatsache her, dass Go eine Multithread-Sprache ist, während „setns“ dies erwartet aus einem Single-Threaded-Kontext aufgerufen. Beim Aufruf aus einer Multithread-Umgebung kann „setns“ den aktuellen Thread nicht richtig mit dem Ziel-Namespace verknüpfen.

Lösung – CGO-Konstruktor-Trick

Eine Lösung für dieses Problem ist die Verwendung von „CGO-Konstruktor-Trick.“ Mit dieser Technik können Sie eine C-Funktion angeben, die ausgeführt werden soll, bevor die Go-Laufzeit initialisiert wird. Mit diesem Ansatz kann Ihre C-Funktion „setns“ aufrufen, bevor die Go-Threads erstellt werden, wodurch sichergestellt wird, dass der Aufruf in einem Single-Threaded-Kontext erfolgt.

  1. Konstruieren Sie eine C-Funktion, die „setns“ aufruft ' mit den gewünschten Parametern. Tun Sie dies, indem Sie die Funktion mit dem Makro __attribute__((constructor)) dekorieren.
  2. Fügen Sie die C-Funktion in Ihren Go-Code ein, indem Sie sie mit import „C“ importieren.

Arbeitsbeispiel

<code class="go">/*
#include <sched.h>
#include <stdio.h>
#include <fcntl.h>

__attribute__((constructor)) void enter_namespace(void) {
   setns(open("/proc/<PID>/ns/mnt", O_RDONLY, 0644), 0);
}
*/
import "C"

... rest of file is unchanged ...
</code>

Denken Sie daran, den Platzhalter mit der tatsächlichen PID des Zielprozesses.

Einschränkungen

Dieser Ansatz weist einige Einschränkungen auf:

  • Die PID muss innerhalb der C-Funktion als Go fest codiert werden Der Code ist zum Zeitpunkt der Ausführung der C-Funktion möglicherweise nicht verfügbar.
  • Es ist nicht möglich, „setns“ mehrmals aus dem Go-Code heraus aufzurufen, da der C-Code vor der Go-Laufzeitinitialisierung ausgeführt wird.

Zusätzliche Hinweise

Ein Patch für „setns(2)“ bestätigt die Anforderung für Single-Thread-Ausführung in Multi-Thread-Umgebungen. Prozesse mit Funktionen müssen außerdem CAP_SYS_CHROOT und CAP_SYS_ADMIN in ihrem eigenen Benutzernamensraum und CAP_SYS_ADMIN im Ziel-Mount-Namensraum besitzen.

Das obige ist der detaillierte Inhalt vonWarum schlägt „setns“ mit EINVAL in einer Go-Multithread-Umgebung fehl?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn