Go: Laufzeit: mlock des Signalstapels fehlgeschlagen: 12

Erstellt am 25. Feb. 2020  ·  128Kommentare  ·  Quelle: golang/go

Welche Version von Go verwenden Sie ( go version )?

 $ go-Version
 go version go1.14rc1 linux/amd64

Reproduziert sich dieses Problem mit der neuesten Version?

Ich habe dies mit golang:1.14-rc-alpine Docker-Image getroffen, der Fehler tritt in 1.13 nicht auf.

Welches Betriebssystem und welche Prozessorarchitektur verwenden Sie ( go env )?

go env Ausgabe

$ gehen env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direkt"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build968395959=/tmp/go-build -gno-record- gcc-Schalter"

Was hast du getan?

Klonen Sie https://github.com/ethereum/go-ethereum , ersetzen Sie die Builder-Version in Dockerfile durch golang:1.14-rc-alpine (oder verwenden Sie das Dockerfile von unten) und

$ docker build .

FROM golang:1.14-rc-alpine

RUN apk add --no-cache make gcc musl-dev linux-headers git

ADD . /go-ethereum
RUN cd /go-ethereum && make geth

Was hast du erwartet zu sehen?

Go sollte unsere Build-Skripte erfolgreich ausführen.

Was hast du stattdessen gesehen?

Step 4/9 : RUN cd /go-ethereum && make geth
 ---> Running in 67781151653c
env GO111MODULE=on go run build/ci.go install ./cmd/geth
runtime: mlock of signal stack failed: 12
runtime: increase the mlock limit (ulimit -l) or
runtime: update your kernel to 5.3.15+, 5.4.2+, or 5.5+
fatal error: mlock failed

runtime stack:
runtime.throw(0xa3b461, 0xc)
    /usr/local/go/src/runtime/panic.go:1112 +0x72
runtime.mlockGsignal(0xc0004a8a80)
    /usr/local/go/src/runtime/os_linux_x86.go:72 +0x107
runtime.mpreinit(0xc000401880)
    /usr/local/go/src/runtime/os_linux.go:341 +0x78
runtime.mcommoninit(0xc000401880)
    /usr/local/go/src/runtime/proc.go:630 +0x108
runtime.allocm(0xc000033800, 0xa82400, 0x0)
    /usr/local/go/src/runtime/proc.go:1390 +0x14e
runtime.newm(0xa82400, 0xc000033800)
    /usr/local/go/src/runtime/proc.go:1704 +0x39
runtime.startm(0x0, 0xc000402901)
    /usr/local/go/src/runtime/proc.go:1869 +0x12a
runtime.wakep(...)
    /usr/local/go/src/runtime/proc.go:1953
runtime.resetspinning()
    /usr/local/go/src/runtime/proc.go:2415 +0x93
runtime.schedule()
    /usr/local/go/src/runtime/proc.go:2527 +0x2de
runtime.mstart1()
    /usr/local/go/src/runtime/proc.go:1104 +0x8e
runtime.mstart()
    /usr/local/go/src/runtime/proc.go:1062 +0x6e

...
make: *** [Makefile:16: geth] Error 2
NeedsInvestigation

Hilfreichster Kommentar

Der Kernel-Bug manifestierte sich in Go 1.13 als zufällige Speicherbeschädigung (sowohl mit als auch ohne präemptives Scheduling). Neu in Go 1.14 ist, dass wir das Vorhandensein des Fehlers erkennen, versuchen, ihn zu umgehen, und es vorziehen, früh und laut abzustürzen, wenn dies nicht möglich ist. Sie können die Details in der Ausgabe sehen, auf die ich Sie verwiesen habe.

Da Sie mich als unehrlich und böse bezeichnet haben, erinnere ich Sie noch einmal an den Verhaltenskodex: https://golang.org/conduct. Ich bin auch fertig mit der Teilnahme an diesem Gespräch.

Alle 128 Kommentare

Dies ist die Folge des Versuchs, einen Kernel-Fehler zu umgehen, der sich erheblich auf Go-Programme auswirkt. Siehe https://github.com/golang/go/issues/35777. Die Fehlermeldung schlägt die einzigen zwei bekannten verfügbaren Fixes vor: Erhöhen Sie das ulimit oder aktualisieren Sie auf einen neueren Kernel.

Die Fehlermeldung schlägt die einzigen zwei bekannten verfügbaren Fixes vor: Erhöhen Sie das ulimit oder aktualisieren Sie auf einen neueren Kernel.

Nun, ich betreibe das offizielle Alpine Docker-Image, dessen Zweck es ist, ein Go-Programm erstellen zu können. Offenbar kann es nicht. IMHO sollte das Upstream-Image dasjenige sein, das behoben wurde, um seinen Zweck zu erfüllen, nicht unsere Build-Infra, um einen Fehler im Upstream-Image zu hacken.

Wird das Alpine-Image vom Go-Team gepflegt? (Echte Frage. Ich weiß es nicht.) So oder so, ja, das Image sollte repariert werden, idealerweise mit einem Kernel-Upgrade.

Ich bin mir nicht ganz sicher, wer und wie die Docker-Images verwaltet (https://hub.docker.com/_/golang), aber das Docker-Hub-Repository ist ein "offizielles Image", das einen sehr schwer zu erhaltenden Status ist. Ich gehe also davon aus, dass jemand, der hoch genug für die Nahrungskette ist, verantwortlich ist.

Es wird "von der Docker-Community gepflegt". Probleme sollten eingereicht werden an

https://github.com/docker-library/golang/issues

BEARBEITEN: Das Problem ist der Host-Kernel, nicht das Docker-Bibliotheksimage, daher können sie es nicht beheben.

Die offizielle Lösung für den Absturz von Go besteht also darin, mit dem Finger auf alle anderen zu zeigen, um Ihren Code zu hacken? Macht Sinn.

@karalabe Ich möchte Sie an https://golang.org/conduct erinnern

Bitte beantworten Sie die Frage

Es ist gängige Praxis, Probleme an das richtige Problemverfolgungssystem weiterzuleiten.

Es gibt eine ausführliche Diskussion möglicher Problemumgehungen und Fixes in dem Problem, auf das ich zuvor verlinkt habe, wenn Sie sehen möchten, welche Optionen auf der Go-Seite in Betracht gezogen wurden.

Dieses Problem tritt bei Go 1.13 nicht auf. Ergo ist dies ein Fehler, der in Go 1.14 eingeführt wurde.

Zu sagen, dass Sie es nicht reparieren können, und Leuten zu sagen, dass sie Problemumgehungen verwenden sollen, ist unehrlich, da das Zurücksetzen eines Codestücks es tatsächlich beheben würde. Eine alternative Lösung wäre, die problematischen Plattformen / Kernel zu erkennen und einen in Go integrierten Fallback-Mechanismus bereitzustellen.

Den Leuten zu sagen, dass sie einen anderen Kernel verwenden sollen, ist besonders unangenehm, weil die meisten Leute nicht herumlaufen und sich einen neuen Kernel bauen können. Wenn Alpine keinen neuen Kernel veröffentlicht, können die meisten Entwickler nicht viel tun. Und schließlich, wenn Ihr Projekt auf eine stabile Infrastruktur angewiesen ist, bei der Sie nicht nur Kernel austauschen können, sind Sie wieder in einer Zwickmühle.

Es ist gängige Praxis, Probleme an das richtige Problemverfolgungssystem weiterzuleiten.

Dass Go abstürzt, liegt nicht an Docker. Das Umleiten eines Go-Absturzes auf ein Docker-Repository ist eine Ablenkung.

Sie können die präventive Planung auch zur Laufzeit deaktivieren

$ GODEBUG=asyncpreemptoff=1 ./your_app

@ianlancetaylor wir haben einen Vorschlag, dies bei der Ausführung auf einem betroffenen Kernel zu tun; ist das machbar?

Übrigens, es ist ein bekanntes Problem, dass Docker-Bibliotheksmodule nicht rechtzeitig aktualisiert werden, was eine Sicherheitshaftung darstellt. Vorbehaltlich Entleerer.

Der Kernel-Bug manifestierte sich in Go 1.13 als zufällige Speicherbeschädigung (sowohl mit als auch ohne präemptives Scheduling). Neu in Go 1.14 ist, dass wir das Vorhandensein des Fehlers erkennen, versuchen, ihn zu umgehen, und es vorziehen, früh und laut abzustürzen, wenn dies nicht möglich ist. Sie können die Details in der Ausgabe sehen, auf die ich Sie verwiesen habe.

Da Sie mich als unehrlich und böse bezeichnet haben, erinnere ich Sie noch einmal an den Verhaltenskodex: https://golang.org/conduct. Ich bin auch fertig mit der Teilnahme an diesem Gespräch.

@karalabe , ich habe mich falsch ausgesprochen, das Problem ist Ihr Hostkernel, nicht das Docker-Image. Können Sie es nicht aktualisieren?

Ich verwende das neueste Ubuntu und den neuesten verfügbaren Kernel. Offenbar sind alle verfügbaren Ubuntu-Kernel für Go 1.14 https://packages.ubuntu.com/search?keywords=linux-image-generic aufgrund der Fehlermeldung ungeeignet.

Können Sie die Ausgabe von $ uname -a zum Hauptproblemtext hinzufügen? Und vielleicht die Goroutine-Stack-Traces entfernen?

Ich habe eine Notiz an golang-dev gepostet.

cc @clements

Wenn Sie sagen, dass Sie auf dem neuesten Ubuntu und Kernel sind, was genau meinen Sie damit (dh Ausgabe von dpkg -l linux-image-*, lsb_release -a, uname -a, so etwas), denn soweit ich das sehen kann fix befindet sich im Kernel in der Update-Tasche sowohl für 19.10 (aktuelle stabile Version) als auch für 20.04 (Entwicklungsversion). Es ist nicht im GA-Kernel für 18.04, aber im HWE-Kernel, aber diese sind nicht mit gcc 9 gebaut und sollten daher sowieso nicht betroffen sein.

@networkimprov Das Deaktivieren der Signalpräemption

Go versucht, den Fehler zu umgehen, indem es den Signalstapel mlockt. Das funktioniert gut, es sei denn, Sie laufen in das Mlock-Limit. Ich nehme an, dass ein Nachteil dieser Problemumgehung darin besteht, dass wir das Problem sehr sichtbar machen, anstatt gelegentlich aufgrund einer zufälligen Speicherbeschädigung fehlzuschlagen, wie es passieren würde, wenn wir den Mlock nicht ausführen würden.

Irgendwann gibt es keine Möglichkeit, einen Kernel-Bug zu umgehen.

@karalabe

Ich verwende das neueste Ubuntu und den neuesten verfügbaren Kernel

$ docker pull -q ubuntu:latest
docker.io/library/ubuntu:latest
$ docker run --rm -i -t ubuntu
root<strong i="9">@e2689d364a25</strong>:/# uname -a
Linux e2689d364a25 5.4.8-050408-generic #202001041436 SMP Sat Jan 4 19:40:55 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

die die Mindestversionsanforderungen erfüllt.

Ähnlich:

$ docker pull -q golang:1.14-alpine
docker.io/library/golang:1.14-alpine
$ docker run --rm -i -t golang:1.14-alpine
/go # uname -a
Linux d4a35392c5b8 5.4.8-050408-generic #202001041436 SMP Sat Jan 4 19:40:55 UTC 2020 x86_64 Linux

Können Sie erklären, was Sie sehen?

@mwhudson

$ dpkg -l linux-image-*
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                   Version      Architecture Description
+++-======================================-============-============-===============================================================
rc  linux-image-4.13.0-16-generic          4.13.0-16.19 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-19-generic          4.13.0-19.22 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-21-generic          4.13.0-21.24 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-25-generic          4.13.0-25.29 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-36-generic          4.13.0-36.40 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-37-generic          4.13.0-37.42 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-38-generic          4.13.0-38.43 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-41-generic          4.13.0-41.46 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.13.0-45-generic          4.13.0-45.50 amd64        Linux kernel image for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-4.15.0-23-generic          4.15.0-23.25 amd64        Signed kernel image generic
rc  linux-image-4.15.0-30-generic          4.15.0-30.32 amd64        Signed kernel image generic
rc  linux-image-4.15.0-32-generic          4.15.0-32.35 amd64        Signed kernel image generic
rc  linux-image-4.15.0-34-generic          4.15.0-34.37 amd64        Signed kernel image generic
rc  linux-image-4.15.0-36-generic          4.15.0-36.39 amd64        Signed kernel image generic
rc  linux-image-4.15.0-39-generic          4.15.0-39.42 amd64        Signed kernel image generic
rc  linux-image-4.15.0-42-generic          4.15.0-42.45 amd64        Signed kernel image generic
rc  linux-image-4.15.0-43-generic          4.15.0-43.46 amd64        Signed kernel image generic
rc  linux-image-4.15.0-45-generic          4.15.0-45.48 amd64        Signed kernel image generic
rc  linux-image-4.15.0-47-generic          4.15.0-47.50 amd64        Signed kernel image generic
rc  linux-image-4.18.0-17-generic          4.18.0-17.18 amd64        Signed kernel image generic
rc  linux-image-5.0.0-13-generic           5.0.0-13.14  amd64        Signed kernel image generic
rc  linux-image-5.0.0-15-generic           5.0.0-15.16  amd64        Signed kernel image generic
rc  linux-image-5.0.0-16-generic           5.0.0-16.17  amd64        Signed kernel image generic
rc  linux-image-5.0.0-17-generic           5.0.0-17.18  amd64        Signed kernel image generic
rc  linux-image-5.0.0-19-generic           5.0.0-19.20  amd64        Signed kernel image generic
rc  linux-image-5.0.0-20-generic           5.0.0-20.21  amd64        Signed kernel image generic
rc  linux-image-5.0.0-21-generic           5.0.0-21.22  amd64        Signed kernel image generic
rc  linux-image-5.0.0-25-generic           5.0.0-25.26  amd64        Signed kernel image generic
rc  linux-image-5.0.0-27-generic           5.0.0-27.28  amd64        Signed kernel image generic
rc  linux-image-5.0.0-29-generic           5.0.0-29.31  amd64        Signed kernel image generic
rc  linux-image-5.0.0-32-generic           5.0.0-32.34  amd64        Signed kernel image generic
rc  linux-image-5.3.0-19-generic           5.3.0-19.20  amd64        Signed kernel image generic
rc  linux-image-5.3.0-22-generic           5.3.0-22.24  amd64        Signed kernel image generic
rc  linux-image-5.3.0-23-generic           5.3.0-23.25  amd64        Signed kernel image generic
rc  linux-image-5.3.0-24-generic           5.3.0-24.26  amd64        Signed kernel image generic
rc  linux-image-5.3.0-26-generic           5.3.0-26.28  amd64        Signed kernel image generic
ii  linux-image-5.3.0-29-generic           5.3.0-29.31  amd64        Signed kernel image generic
ii  linux-image-5.3.0-40-generic           5.3.0-40.32  amd64        Signed kernel image generic
rc  linux-image-extra-4.13.0-16-generic    4.13.0-16.19 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-19-generic    4.13.0-19.22 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-21-generic    4.13.0-21.24 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-25-generic    4.13.0-25.29 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-36-generic    4.13.0-36.40 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-37-generic    4.13.0-37.42 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-38-generic    4.13.0-38.43 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-41-generic    4.13.0-41.46 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
rc  linux-image-extra-4.13.0-45-generic    4.13.0-45.50 amd64        Linux kernel extra modules for version 4.13.0 on 64 bit x86 SMP
ii  linux-image-generic                    5.3.0.40.34  amd64        Generic Linux kernel image

$ lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 19.10
Release:    19.10
Codename:   eoan
$ uname -a

Linux roaming-parsley 5.3.0-40-generic #32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ sudo apt-get dist-upgrade 

Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

@myitcv

FROM golang:1.14-alpine
RUN  apk add --no-cache make gcc musl-dev linux-headers git wget

RUN \
  wget -O geth.tgz "https://github.com/ethereum/go-ethereum/archive/v1.9.11.tar.gz" && \
  mkdir /go-ethereum && tar -C /go-ethereum -xzf geth.tgz --strip-components=1 && \
  cd /go-ethereum && make geth
$ docker build .

Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM golang:1.14-alpine
1.14-alpine: Pulling from library/golang
c9b1b535fdd9: Already exists 
cbb0d8da1b30: Already exists 
d909eff28200: Already exists 
8b9d9d6824f5: Pull complete 
a50ef8b76e53: Pull complete 
Digest: sha256:544b5e7984e7b2e7a2a9b967bbab6264cf91a3b3816600379f5dc6fbc09466cc
Status: Downloaded newer image for golang:1.14-alpine
 ---> 51e47ee4db58

Step 2/3 : RUN  apk add --no-cache make gcc musl-dev linux-headers git wget
 ---> Running in 879f98ddb4ff
[...]
OK: 135 MiB in 34 packages
Removing intermediate container 879f98ddb4ff
 ---> 9132e4dae4c3

Step 3/3 : RUN   wget -O geth.tgz "https://github.com/ethereum/go-ethereum/archive/v1.9.11.tar.gz" &&   mkdir /go-ethereum && tar -C /go-ethereum -xzf geth.tgz --strip-components=1 &&   cd /go-ethereum && make geth
 ---> Running in a24c806c60d3
2020-02-26 07:18:54--  https://github.com/ethereum/go-ethereum/archive/v1.9.11.tar.gz
[...]
2020-02-26 07:18:58 (2.48 MB/s) - 'geth.tgz' saved [8698235]

env GO111MODULE=on go run build/ci.go install ./cmd/geth
runtime: mlock of signal stack failed: 12
runtime: increase the mlock limit (ulimit -l) or
runtime: update your kernel to 5.3.15+, 5.4.2+, or 5.5+
fatal error: mlock failed

Entschuldigung, mein vorheriger Kommentar war irreführend. Denn natürlich wird die Kernel-Version, die uname -a im Docker-Container zurückgibt, die des Hosts sein.

Daher pro:

$ uname -a

Linux roaming-parsley 5.3.0-40-generic #32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Sie müssen den Host-Betriebssystemkernel aktualisieren.

FWIW, die Schritte, die Sie oben mit Alpine zu make geth funktionieren für mich.:

...
Done building.
Run "./build/bin/geth" to launch geth.

Ja, aber in meinen vorherigen Beiträgen habe ich hervorgehoben, dass ich bereits auf dem neuesten Ubuntu bin und den neuesten verfügbaren Kernel aus dem Paket-Repository installiert habe. Ich sehe nicht, wie ich meinen Kernel aktualisieren könnte, damit er mit Go 1.14 funktioniert, außer den gesamten Kernel aus dem Quellcode neu zu erstellen. Vielleicht übersehe ich etwas?

Um nur zu betonen, dass ich verstehe, was die Problemumgehung ist, und wenn ich es zum Laufen bringen möchte, kann ich es. Ich habe diesen Problembericht geöffnet, weil ich erwarte, dass andere Leute irgendwann auf dasselbe Problem stoßen. Wenn nur ein Update meines Systems das Problem beheben würde, würde ich dies gerne als Lösung akzeptieren, aber wenn ich nichts vermisse, ist der behobene Kernel für (neue) Ubuntu-Benutzer nicht verfügbar, sodass eine ziemlich große Benutzerbasis betroffen sein könnte.

Ja, aber in meinen vorherigen Beiträgen habe ich hervorgehoben, dass ich bereits auf dem neuesten Ubuntu bin und den neuesten verfügbaren Kernel aus dem Paket-Repository installiert habe. Ich sehe nicht, wie ich meinen Kernel aktualisieren könnte, damit er mit Go 1.14 funktioniert, außer den gesamten Kernel aus dem Quellcode neu zu erstellen. Vielleicht übersehe ich etwas?

Hm ja, ich habe gerade auch auf Brennweite reproduziert. Der Fix ist im Git für den Ubuntu-eoan-Kernel vorhanden: https://kernel.ubuntu.com/git/ubuntu/ubuntu-eoan.git/commit/?id=59e7e6398a9d6d91cd01bc364f9491dc1bf2a426 und dieser Commit ist im Vorläufer für die 5.3. 0-40.32, also sollte sich der Fix im verwendeten Kernel befinden. Mit anderen Worten, ich denke, wir müssen das Kernel-Team einbeziehen – das werde ich versuchen.

@karalabe - Ich habe gerade meinen Fehler erkannt: Obwohl ich das neueste Ubuntu verwende, verwende ich tatsächlich eoan .

@mwhudson - nur eine Sache zu beachten (obwohl Sie dies wahrscheinlich bereits wissen), ein oberflächlicher Blick auf den Code, der für diesen Schalter verantwortlich ist:

https://github.com/golang/go/blob/20a838ab94178c55bc4dc23ddc332fce8545a493/src/runtime/os_linux_x86.go#L56 -L61

scheint darauf hinzudeuten, dass die Go-Seite nach Patch-Release 15 oder höher sucht. Was meldet 5.3.0-40.32 als Patch-Version? Ich vermute 0?

Eröffnen Sie diese Diskussion erneut, bis wir das Problem hier abschließen.

Eine kleine Zusammenfassung, weil ich es mir selbst zusammensetzen musste:

Es scheint also, als wäre der Kernel von Ubuntu gepatcht, aber die Problemumgehung wird trotzdem aktiviert.

Es scheint also, als wäre der Kernel von Ubuntu gepatcht, aber die Problemumgehung wird trotzdem aktiviert.

Oh richtig, ja, ich sollte eigentlich den Fehler lesen, oder? Dies ist eher die Problemumgehung als der ursprüngliche Fehler, wenn die Problemumgehung nicht wirklich benötigt wird, Go jedoch keine gute Möglichkeit gibt, dies zu erfahren. Ich kann das Auschecken des Go 1.14-Pakets in Ubuntu patchen, aber das hilft Benutzern nicht, die zB das Docker golang:1.14-alpine- Image

Ich schätze, die Frage ist, wie viele Benutzer derzeit "angreifbare" Kernel verwenden. Es kann nicht mehr viele Distributionen geben, die mit gcc 9 einen ungepatchten Kernel kompilieren.

So viele kann es nicht geben...

Berühmte letzte Worte? :D

Aber im Ernst, ich glaube nicht, dass die Leute häufig Kernel aktualisieren, und viele Systeme können dies nicht. Vielleicht wäre eine bessere Frage zu stellen, welche Systeme/Distributionen standardmäßig anfällige Kernel verwenden und einfach davon ausgehen, dass viele Leute darauf stecken bleiben.

Ich kann das Auschecken des Go 1.14-Pakets in Ubuntu patchen, aber das hilft Benutzern nicht, die zB das Docker golang:1.14-alpine- Image

Sie würden auch Benutzer vermissen, die aus dem Quellcode erstellen. Ethereum macht beispielsweise Source-Builds für unsere PPAs, weil es kein aktuelles Go-Bundle für alle Distributionen auf Launchpad gibt.

Ist es bei Ubuntu (und anderen Distributionen?) üblich, Rosinenpickerei zu verwenden, anstatt den Linux-Kernel-Patch-Versionen zu folgen? Auf https://packages.ubuntu.com/search?keywords=linux-image-generic haben alle Kernel ein Patch-Release von null.

Was eine schnelle Google-Suche angeht, veröffentlicht Ubuntu keine neuen Kernel, nachdem sie die Distribution ausgeliefert haben, sondern nur Rosinenpick-Sicherheitskorrekturen (dh kein Patch-Versions-Bump). Ausgenommen davon sind LTS-Versionen (unterstützt für 5 Jahre), die möglicherweise alle paar Jahre Kernel-Updates erhalten, um neue Hardware zu unterstützen (aber das ist auch sehr selten). Kenne keine anderen Distributionen.

Mit meinem begrenzten Wissen im Moment scheint das seltsam. Patch-Releases sollen Patches auf kontrollierte Weise verteilen, damit die Leute (und in diesem Fall die Go-Laufzeit) wissen, welche Patches enthalten sind und welche nicht. Aber das ist so, also müssen wir damit leben.

Offene Fragen:

  • Wie viele Menschen sind von diesem Problem betroffen?
  • Ist ulimit eine praktikable Problemumgehung?
  • Ist Ubuntu die einzige Distribution, die Linux-Kernel-Patch-Nummern "ignoriert"?
  • Abhängig von den Antworten auf die obigen Fragen: Wäre es sinnvoll, eine spezielle Erkennung für Ubuntu hinzuzufügen?

@neelance

Ist es bei Ubuntu (und anderen Distributionen?) üblich, Rosinenpickerei zu verwenden, anstatt den Linux-Kernel-Patch-Versionen zu folgen?

Viele Distributionen tun dies, nicht nur Ubuntu. Debian macht es, Red Hat Enterprise Linux macht es und ich erwarte, dass SUSE es auch für ihre Unternehmensdistributionen tut. Rosinenpicken ist der einzige Weg, um Fehler zu beheben, wenn Sie den stabilen Releases der Upstream-Seite nicht aggressiv folgen können (und die stabilen Releases wechseln, wenn der Upstream-Support wegfällt). Fedora ist eine Ausnahme; es rebasiert nach einer Weile auf den neuesten stabilen Upstream-Kernel.

Es gibt auch die Frage der proprietären Kernel, die von Container-Engines verwendet werden. Wir können uns nicht einmal die Quellen dafür ansehen, und einige von ihnen haben in der Vergangenheit über Kernel-Versionsnummern gelogen. Ich gehe davon aus, dass sie auch Rosinenpickerei verwenden.

Im Allgemeinen sind Versionsprüfungen für Kernel-Features (oder Bugs) eine wirklich schlechte Idee. Für Go ist es aufgrund der statischen Verlinkung schlimmer, sodass es unmöglich ist, die Laufzeit unter einer Anwendung auszulagern, um ihre Kernel-Erwartungen zu erfüllen.

Ist es bei Ubuntu (und anderen Distributionen?) üblich, Rosinenpickerei zu verwenden, anstatt den Linux-Kernel-Patch-Versionen zu folgen? Auf https://packages.ubuntu.com/search?keywords=linux-image-generic haben alle Kernel ein Patch-Release von null.

Der String der Basis-Kernel-Version ändert sich nicht, das stimmt. Dies bedeutet jedoch nicht, dass die Stable-Releases der Upstream-Seite nicht zusammengeführt werden, sondern die ABI-Nummer wird stattdessen erhöht, wenn Codeänderungen vorgenommen werden.

Beachten Sie, dass Sie das Meta-Paket ausgewählt haben, das nicht das richtige Changelog anzeigt. Hier können Sie sehen, dass die neueste Version 5.4.0-14.17 die stabile Version 5.4.18 zusammengeführt hat:
http://changelogs.ubuntu.com/changelogs/pool/main/l/linux-5.4/linux-5.4_5.4.0-14.17/changelog

Es hört sich so an, als ob eine ordnungsgemäße automatische Erkennung über alle Distributionen hinweg fast unmöglich ist. Ich sehe drei Möglichkeiten:

  • Nichts tun.
  • Aktivieren Sie die Problemumgehung.
  • Nehmen Sie den Workaround-Opt-out vor.

Oder deaktivieren Sie die asynchrone Voreinstellung standardmäßig auf 5.3.x und 5.4.x und lassen Sie sie von Benutzern zur Laufzeit aktivieren.

https://github.com/golang/go/issues/37436#issuecomment -591237929 besagt, dass das Deaktivieren der asynchronen Voreinstellung keine richtige Lösung ist, oder?

Genau genommen nicht, aber es gab keine Berichte über das Problem, bevor die asynchrone Präemption gelandet ist.

Könnte die Laufzeit tatsächlich beim Start (für 5.3.x & 5.4.x) einen untergeordneten Prozess abspalten, der den Fehler auslöst und die Problemumgehung aktivieren, wenn dies der Fall ist? IIRC gibt es einen zuverlässigen Reproduzierer, siehe https://github.com/golang/go/issues/35326#issuecomment -558690446

Das Deaktivieren der asynchronen Voreinstellung ist eine Ablenkung. Programme, die auf fehlerhaften Kerneln laufen, sind immer noch kaputt. Es ist nur so, dass sich die Defekte als seltsame Speicherbeschädigung und nicht als Fehler über das Durchlaufen eines mlock Limits zeigen, das auf Kernel-Versionen hinweist. Obwohl wir das Problem offensichtlich vollständig beheben möchten, denke ich, dass wir bei der Wahl zwischen einem eindeutigen Fehler oder einer zufälligen Speicherbeschädigung immer den eindeutigen Fehler auswählen sollten.

Ich stimme zu, dass die Erkennung der Kernel-Version schrecklich ist, es ist nur so, dass wir keine andere Option kennen. Falls jemand diesbezüglich Vorschläge hat, wäre das sehr hilfreich.

Eine Sache, die wir tun könnten, ist eine GODEBUG Einstellung hinzuzufügen, um die mlock des Signalstapels zu deaktivieren. Das würde den Leuten einen Workaround geben, der sich auf das eigentliche Problem konzentriert. Wir können diese Einstellung in der Fehlermeldung erwähnen. Ich befürchte, dass es dazu führen wird, dass die Leute die Einstellung aktivieren, unabhängig davon, ob sie einen gepatchten Kernel haben oder nicht. Aber zumindest wird es Leuten, die wirklich einen gepatchten Kernel haben, eine Möglichkeit geben, dieses Problem zu umgehen. CC @aclements

Könnte die Laufzeit tatsächlich beim Start (für 5.3.x & 5.4.x) einen untergeordneten Prozess abspalten, der den Fehler auslöst und die Problemumgehung aktivieren, wenn dies der Fall ist? IIRC gibt es einen zuverlässigen Reproduzierer, siehe #35326 (Kommentar)

Es ist eine interessante Idee, aber ich denke, dass der Test in diesem Fall viel zu teuer ist, um ihn beim Start für jedes einzelne Go-Programm auszuführen.

Ich habe vielleicht etwas übersehen (dieser Thread wurde schnell lang!), aber was ist der Nachteil oder die Schwierigkeit, einfach das Mlock-Limit zu erhöhen? Es gibt keinen Grund, es nicht einfach auf unbegrenzt zu setzen, aber selbst wenn Sie das nicht möchten, benötigen Sie nur 4 KiB pro Thread, also sind nur 64 MiB buchstäblich mehr, als die Laufzeit eines einzelnen Prozesses zum Mlocken fähig ist . AFAIK, die meisten Distributionen lassen es standardmäßig unbegrenzt. Die einzige bemerkenswerte Ausnahme, die mir bekannt ist, ist Docker, das es standardmäßig auf (ich glaube) 64 KiB festlegt, aber dies kann ausgelöst werden, indem --ulimit memlock=67108864 an Docker übergeben wird.

Es scheint, als hätten wir bereits eine ziemlich einfache Problemumgehung. Gibt es etwas, das die Leute daran hindert, dies zu tun?

Der Punkt des Problems ist, dass Sie nach Möglichkeit keinen manuellen Workaround anwenden müssen. Es sieht aus wie eine Regression in 1.14.

Es kann auf der Seite der Docker-Bibliothek nicht behoben werden: https://github.com/docker-library/golang/issues/320

Das Problem mit dem ulimit Workaround ist, dass es eine Zeitbombe ist. Derzeit muss bei Go 1.13 kein automatisierter Prozess das Ulimit erhöhen. Jeder, bei dem Go 1.14 sofort nach dem Update fehlschlägt, wird es bemerken und beheben.

Das interessantere Szenario ist, was passiert, wenn jemand eine alte Version eines nicht betroffenen Kernels verwendet und den Kernel irgendwann auf einen neuen umstellt. Plötzlich werden die Dinge kaputt gehen, aber da Go die App-Schicht ist und der Kernel die Betriebssystemschicht ist, wird es einige Zeit dauern, die Verbindung herzustellen und eine Lösung zu finden. Die Frage ist, wie hoch die Kosten sein werden.


Was jedoch nicht sofort klar ist, ist, ob nur der Go-Compiler oder alle von Go erstellten Apps auch Probleme haben? Wenn nur der Compiler, ist das ein Glücksfall und der Fallout kann eingedämmt werden. Wenn jedoch alle Go-Apps, die mit 1.14 erstellt wurden, zur Panik neigen, könnte dies die vorgefertigte Binärportabilität wirklich beeinträchtigen, da mein Code plötzlich auf einem anderen System nicht funktionieren könnte (das ist eigentlich völlig gültig, verwendet nur einen anderen Kernel Versionierungsschema).

Was jedoch nicht sofort klar ist, ist, ob nur der Go-Compiler oder alle von Go erstellten Apps auch Probleme haben?

Der Linux-Kernel-Bug ist nicht einmal Go-spezifisch. Wenn ich das richtig verstehe, betrifft es jedes Programm – sogar eines, das in C geschrieben ist! — das die XMM- oder YMM-Register verwendet und Signale empfangen kann. Go-Programme unter 1.14 sind _stärker_ betroffen als viele andere Programme, weil sie intern Signale für die Vorbeugung von Goroutinen verwenden, und deshalb enthält die Go 1.14-Laufzeit die mlock Abhilfe.

Der Linux-Kernel-Bug ist nicht einmal Go-spezifisch.

Ja, aber mein Kernel ist gepatcht, aber Go gerät immer noch in Panik :)

@aclements

Die einzige bemerkenswerte Ausnahme, die mir bekannt ist, ist Docker, das es standardmäßig auf (ich glaube) 64 KiB festlegt, aber dies kann durch Übergabe von --ulimit memlock=67108864 an Docker ausgelöst werden.

Es scheint, als hätten wir bereits eine ziemlich einfache Problemumgehung. Gibt es etwas, das die Leute daran hindert, dies zu tun?

Leider ja. In unserem Fall hier können wir unseren Kunden nicht sagen, dass sie ihre Docker-Container neu konfigurieren sollen. Es gibt zu viele und sie reagieren empfindlich auf Umgebungsänderungen in ihren Setups; Aus diesem Grund haben wir uns entschieden, die Anwendung in einem Docker-Container bereitzustellen, damit die Fassade eines Isolationstools die Sorge um das Ändern der Konfigurationsoptionen erleichtert. Das Ändern des Containerinhalts ist in Ordnung, aber wie wir den Container aufrufen, ist möglicherweise nicht so gut.

@aclements

Es gibt keinen Grund, es nicht einfach auf unbegrenzt zu setzen, aber selbst wenn Sie das nicht möchten, benötigen Sie nur 4 KiB pro Thread, also sind nur 64 MiB buchstäblich mehr, als die Laufzeit eines einzelnen Prozesses zum Mlocken fähig ist . AFAIK, die meisten Distributionen lassen es standardmäßig unbegrenzt.

Das scheint nicht der Fall zu sein - dies ist ein Ubuntu LTS mit nur 6KiB im Sperrraum:

~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3795
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3795
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.6 LTS
Release:    16.04
Codename:   xenial
~$ uname -a
Linux bastion0 4.4.0-174-generic #204-Ubuntu SMP Wed Jan 29 06:41:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Was ist der Inhalt von /proc/version für einen Beispiel-Kernel, der gepatcht wurde, um korrekt zu funktionieren, aber für den Go derzeit den mlock Fehler erzeugt? Danke.

@ucirello Sehen Sie Probleme beim Ausführen von Go-Programmen auf dem von Ihnen beschriebenen System?

$ cat /proc/version
Linux version 5.3.0-40-generic (buildd@lcy01-amd64-026) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020

Vielleicht könnten wir das in /proc/version aufgezeichnete Datum als zusätzliches Signal verwenden. Es sollte wahrscheinlich Release-spezifisch sein, was ein Schmerz ist. Aber das Ganze tut weh.

In der Diskussion scheint es darum zu gehen, entweder mehr falsch-positive oder falsch-negative zu akzeptieren. Hier ist eine Zusammenfassung:

Falsch positiv: Der Workaround wird auf einem gepatchten Kernel aktiviert.

  • Reproduzierbar. Anleitungen können gezeigt werden.
  • Sieht nach einer Regression aus.
  • In bestimmten Umgebungen schwer zu beheben.
  • Go Binary kann in einigen Umgebungen ausgeführt werden, in anderen jedoch nicht.

Falsch negativ: Die Problemumgehung ist auf einem ungepatchten Kernel nicht aktiviert.

  • Ein Fehler tritt nur selten auf, insbesondere wenn die asynchrone Voreinstellung deaktiviert ist.
  • Möglicherweise schwerwiegende Folgen aufgrund von Speicherbeschädigungen.
  • Schwer zu debuggen.

@ianlancetaylor Ich sehe keine Probleme in dem beschriebenen System, aber

Auf jeden Fall wollte ich hervorheben, dass die Annahme, dass die meisten Distributionen ulimit -l mit 64 ulimit -l 64 KB beträgt - und es handelt sich um eine Standardinstallation.

Gibt es eine Möglichkeit, die Einstellung ulimit zu erkennen und den Absturz zu vermeiden, wenn die Problemumgehung nicht angewendet werden kann? Auf diese Weise könnten wir die Situation noch verbessern, aber keine neuen Abstürze verursachen? Wir könnten dann stattdessen eine Warnung über eine potenzielle Speicherbeschädigung ausgeben.

Gibt es eine Möglichkeit, die ulimit-Einstellung zu erkennen und den Absturz zu vermeiden, wenn die Problemumgehung nicht angewendet werden kann?

Tatsächlich erkennt der aktuelle Code bereits die ulimit-Einstellung. Es fragt es nicht direkt ab, aber es erkennt, wenn es darauf stößt, weshalb es diese spezielle Fehlermeldung ausgibt, in der der Benutzer aufgefordert wird, das ulimit zu erhöhen. Wenn etwas anderes beim Mlocking schief geht, wird tatsächlich eine andere Nachricht gedruckt. Der Absturz ist beabsichtigt, da wir dies einer zufälligen Speicherbeschädigung vorziehen.

Auf jeden Fall möchte ich hervorheben, dass die Annahme, dass die meisten Distributionen ulimit -lwith 64M liefern, falsch zu sein scheint. Dies ist eine Linux-Box, deren ulimit -l 64K beträgt - und es handelt sich um eine Standardinstallation.

@ucirello , danke für diesen Datenpunkt. Ich habe keine Ubuntu-Box zur Hand, aber ich habe das ursprüngliche Debugging bei einer Ubuntu-Installation durchgeführt und hätte schwören können, dass es keinen Ulimit-Satz gab. Das ist definitiv kein Container?

@ianlancetaylor Ich habe ein schnelles und schmutziges Skript erstellt, um zu überprüfen, was Uname meldet: https://gist.github.com/Tasssadar/7424860a2764e3ef42c7dcce7ecfd341

Hier ist das Ergebnis aktueller (na ja, -ish) Debian-Tests:

tassadar<strong i="9">@dorea</strong>:~/tmp$ go run gouname.go 
real uname
Linux dorea 5.4.0-3-amd64 #1 SMP Debian 5.4.13-1 (2020-01-19) x86_64 GNU/Linux

our uname
sysname Linux
nodename dorea
release 5.4.0-3-amd64  <-- used by go
version #1 SMP Debian 5.4.13-1 (2020-01-19)
machine x86_64
domainname (none)

Da Go nur den Release-String verwendet, funktioniert die Patch-Versionsprüfung grundsätzlich nirgendwo außer auf Vanilla-Kerneln - sowohl Debian als auch RHEL/CentOS (das zum Glück einen zu alten Kernel hat) tun dies so, sie behalten die .0 und geben die an echte Patch-Version später. Leider verwenden sie nicht dasselbe Format für version .

BEARBEITEN: Und um es noch umständlicher zu machen, fügt Ubuntu die Patch-Nummer überhaupt nicht in uname ein, obwohl sie wahrscheinlich alle Fixes integriert haben. Vielleicht ist die beste Vorgehensweise, dies zu einer Warnung anstatt zu einem Absturz zu machen? Zu diesem Zeitpunkt sind die meisten Kernel wahrscheinlich sowieso bereits aktualisiert.

Der Absturz ist beabsichtigt, da wir dies einer zufälligen Speicherbeschädigung vorziehen.

@aclements Es gibt einen kleinen Fehler in diesem Argument: Das Problem sind nicht die True Positives, die in das ulimit laufen, sondern die False Positives, die ohne die Problemumgehung keine Speicherbeschädigung hätten.

@aclements

Das ist definitiv kein Container?

Ich bin mir zu 100% sicher, dass es kein Container ist. Es ist jedoch eine VM.

$ sudo virt-what
xen
xen-hvm

@ucirello , danke für diesen Datenpunkt. Ich habe keine Ubuntu-Box zur Hand, aber ich habe das ursprüngliche Debugging bei einer Ubuntu-Installation durchgeführt und hätte schwören können, dass es keinen Ulimit-Satz gab. Das ist definitiv kein Container?

Als anderen Datenpunkt ist mein Ubuntu Eoan-Hauptsystem als 64 MB standardmäßig auf ulimit -l .

@ucirello Es gibt kein Problem mit 4.4.x Linux-Kerneln. Der Fehler trat erstmals in der Kernel-Version 5.2 auf.

@ianlancetaylor - danke für die Informationen. Da habe ich wohl die Fehlermeldung falsch interpretiert. Ich wusste nichts von dieser Tatsache, und die Fehlermeldung ließ glauben, dass die neuen Binärdateien mit älteren Kerneln nicht kompatibel wären.

Go-Programme melden die Fehlermeldung nur bei Kerneln mit einer Versionsnummer, die darauf hinweist, dass das Problem möglicherweise vorliegt.

Hier ist etwas, was wir tun könnten:

  1. Verwenden Sie uname , um die Kernel-Version auf einen anfälligen Kernel zu überprüfen, wie wir es heute tun.
  2. Wenn der Kernel je nach Version angreifbar ist, lesen Sie /proc/version .
  3. Wenn /proc/version die Zeichenfolge "2020" , nehmen Sie an, dass der Kernel gepatcht ist.
  4. Wenn /proc/version die Zeichenfolge "gcc version 8" /proc/version enthält, gehe davon aus, dass der Kernel auch nach einem Patch funktioniert (da der Fehler nur auftritt, wenn der Kernel mit GCC 9 oder höher kompiliert wird).
  5. Rufen Sie andernfalls mlock auf Signal-Stacks auf, wie wir es heute auf anfälligen Kerneln tun.

Der Sinn hiervon besteht darin, die Häufigkeit zu reduzieren, in der Go-Programmen keinen mlock Speicherplatz mehr haben.

Kennt jemand ungepatchte Kernel, die möglicherweise die Zeichenfolge "2020" in /proc/version ?

Aus Sicherheitsgründen sollten wir wahrscheinlich versuchen, die Zeiten zu ermitteln, zu denen der Kernel für die großen Distributionen gepatcht wurde. Gibt es jemanden, der das für eine bestimmte Distribution identifizieren kann? Danke.

Ich bin mir nicht sicher, ob dies überhaupt hilfreich ist, aber Ubuntu stellt anscheinend die Standard-Kernel-Version für diejenigen zur Verfügung, die suchen:

$ cat /proc/version_signature
Ubuntu 5.3.0-1013.14-azure 5.3.18

@jrockway Danke, das Problem ist nicht, dass wir keine Kernel-Version haben, sondern dass Ubuntu eine Kernel-Version verwendet, die den Fehler hat, aber Ubuntu hat einen Patch für den Fehler angewendet, also funktioniert der Kernel tatsächlich, aber wir tun es nicht Ich weiß nicht, wie man diese Tatsache erkennt.

Ergänzend zur String-Matching-Heuristik von /proc/version auf prüfen
5.3.x && x >= 15 || 5.4.x && x >= 2 (kein echter Code, aber Sie bekommen die Idee)

Danke, das haben wir bereits in den uname Ergebnissen überprüft.

Ich beziehe mich auf https://github.com/golang/go/issues/37436#issuecomment -591503305:

release 5.4.0-3-amd64  <-- used by go
version #1 SMP Debian 5.4.13-1 (2020-01-19) <-- has actual version

BEARBEITEN: Unter Ubuntu können Sie /proc/version_signature wie von mir vorgeschlagen überprüfen.

Ah, tut mir leid, das habe ich übersehen. Laut diesem Kommentar unterscheiden sich auf einigen Systemen das release Feld und das version Feld, die von uname Bezug auf die Kernel-Version, die sie melden. Wir prüfen derzeit das Feld release , aber nicht das Feld version .

Die Datei /proc/version enthält wieder andere Informationen.

Mein Ubuntu-System hat /proc/version , aber nicht /proc/version_signature .

@bbarenblat hat hilfreicherweise uname und /proc/version aus mehreren Versionen mehrerer Distributionen gesammelt, um zu sehen, wie sie in freier Wildbahn aussehen (ich habe einige meiner eigenen hinzugefügt):

Debian instabil:

$ uname -v
#1 SMP Debian 5.3.9-3 (2019-11-19)
$ uname -r
5.3.0-2-amd64
$ cat /proc/version
Linux version 5.3.0-2-amd64 ([email protected]) (gcc version 9.2.1 20191109 (Debian 9.2.1-19)) #1 SMP Debian 5.3.9-3 (2019-11-19)

Debian 10.3 (aktuell stabil):

$ uname -v
#1 SMP Debian 4.19.98-1 (2020-01-26)
$ uname -r
4.19.0-8-amd64
# cat /proc/version
Linux version 4.19.0-8-amd64 ([email protected]) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.98-1 (2020-01-26)

Debian 7 (sehr alt):

$ uname -v
#1 SMP Debian 3.2.78-1
$ uname -r
3.2.0-4-amd64
$ cat /proc/version
Linux version 3.2.0-4-amd64 ([email protected]) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Debian 3.2.78-1

Debian „irgendwo nach Stable, mit dem gelegentlichen Unstable-Paket“:

$ uname -v
#1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20)
$ uname -r
4.19.0-6-amd64
$ cat /proc/version
Linux version 4.19.0-6-amd64 ([email protected]) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20)

Ubuntu 19.10:

$ uname -v
#32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020
$ uname -r
5.3.0-40-generic
$ cat /proc/version  
Linux version 5.3.0-40-generic (buildd@lcy01-amd64-026) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #32-Ubuntu SMP Fri Jan 31 20:24:34 UTC 2020

Ubuntu 19.10 mit GCP-Kernel (das ist wirklich 5.3.0):

$ uname -v
#9-Ubuntu SMP Mon Nov 11 09:52:23 UTC 2019
$ uname -r
5.3.0-1008-gcp
$ cat /proc/version
Linux version 5.3.0-1008-gcp (buildd@lgw01-amd64-038) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #9-Ubuntu SMP Mon Nov 11 09:52:23 UTC 2019

Ubuntu 19.10 mit handgebautem Kernel:

$ uname -v
#36 SMP Wed Feb 26 20:55:52 UTC 2020
$ uname -r
5.3.10
$ cat /proc/version
Linux version 5.3.10 (austin@austin-dev-ubuntu) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #36 SMP Wed Feb 26 20:55:52 UTC 2020

CentOS 7.7:

$ uname -v
#1 SMP Fri Dec 6 15:49:49 UTC 2019
$ uname -r
3.10.0-1062.9.1.el7.x86_64
$ cat /proc/version
Linux version 3.10.0-1062.9.1.el7.x86_64 ([email protected]) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Fri Dec 6 15:49:49 UTC 2019

@aclements Ich bin etwas verwirrt darüber, welche der von Ihnen geposteten Kernel den Workaround benötigen und welche bereits gepatcht sind. Vielleicht könntest du deinen Beitrag kommentieren.

Das Problem ist, dass Sie, wenn Sie sich innerhalb der potenziell ungültigen Versionsbereiche befinden, _betroffen sein könnten_, wenn Sie sich außerhalb des Versionsbereichs befinden, sind Sie in Sicherheit.
Als die anfängliche Beschädigung festgestellt wurde, haben wir den Patch sofort gezogen, getestet und ausgerollt. Unser Kernel war also 100% im schlechten Bereich, aber gepatcht. Außerhalb des Bereichs zu sein bedeutet, dass Sie sicher sind, aber innerhalb des Bereichs können Sie nicht beweisen, dass der Fehler existiert, ohne ihn zu testen. (Mit anderen Worten: Fehlalarme werden absichtlich auftreten)

Ich baue gerade einen weiteren gepatchten Ubuntu-Kernel mit Upstream-Versionsnummern

  • make kernelversion
  • debian{,.master}/{changelog,control} mit dieser Version patchen

Software, die auf der Kernel-Version basiert, ist der Grund, warum Distributionen diese gerne stabil halten: Wenn ein Update auf die Versionsnummer Software beschädigen könnte, die zuvor funktionierte, ist es besser, die Version nicht zu ändern (aber trotzdem die Patches zu installieren!).

Ich bin nicht glücklich, nur wegen Golang 1.14 einen neuen Kernel zu rollen, aber ich denke, es wird funktionieren.
Ich würde jedem davon abraten, Golang 1.14-Binärdateien außerhalb von kontrollierten Umgebungen zu versenden.

Der Beitrag von @rtreffer klingt wieder so, als Ergebnisse unvermeidlich. Derzeit stimme ich immer noch für die Lösung, die negativen Auswirkungen eines False Positive zu begrenzen.

Ich denke, es sollte ein Opt-In sein, um alle falsch positiven Ergebnisse zu vermeiden. Fügen Sie beispielsweise GOWORKAROUNDS env var boolean oder mit einer Liste von Problemumgehungen hinzu oder aktivieren Sie die Heuristik, diese zu finden.

Dies wäre die am wenigsten aufdringliche Lösung IMO.

@fcuello-fudo Das Problem besteht darin, dass die Symptome sehr unklar sind, wenn die Problemumgehung auf einem fehlerhaften Kernel nicht aktiviert ist.

Wie wäre es mit der Wiederverwendung des "befleckten" Konzepts aus dem Linux-Kernel? Die Go-Laufzeit würde weiterhin fehlerhafte Kernel erkennen und den mlock-Workaround anwenden, markiert sich jedoch selbst als verdorben, wenn mlock fehlschlägt (und nicht abstürzt). Stellen Sie dann sicher, dass Sie bei Paniken und Meldungen eine Notiz hinzufügen, wenn das Taint-Flag gesetzt ist.

Der Vorteil ist, dass falsch positive Abstürze vermieden werden und dennoch ein klarer Hinweis für den Fall geboten wird, dass ein schlechter Kernel einen Absturz verursacht.

Der Nachteil ist, dass ein fehlerhafter Kernel den Speicher im Hintergrund beschädigen kann, ohne dass es zu einem sichtbaren Absturz kommt.

@fcuello-fudo Das Problem besteht darin, dass die Symptome sehr unklar sind, wenn die Problemumgehung auf einem fehlerhaften Kernel nicht aktiviert ist.

Und es standardmäßig aktiviert zu lassen, aber es wäre dennoch nützlich, Problemumgehungen zu deaktivieren, wenn der Benutzer dies wünscht?

@howardjohn (primärer https://github.com/istio/istio/issues/21672 :

Mein Kernel auf meinem persönlichen Computer ist nicht gepatcht. Aber es spielt keine Rolle, was mein Computer hat, wir versenden Istio an Tausende von Benutzern. Ich kann nicht kontrollieren, auf welcher Maschine es ausgeführt wird, und ich würde das gerne nicht auf eine Teilmenge von Kernel-Versionen beschränken müssen

Das Prometheus-Projekt hält auch sein go1.14-Upgrade zurück: https://github.com/prometheus/golang-builder/pull/85#issuecomment -592082645

Ich bin auf dieses Problem gestoßen, als ich go-Anwendungen auf einem selbst gehosteten Kubernetes-Cluster ausgeführt habe. Ich konnte zulassen, dass der _mlock_-Workaround wirksam wird, indem ich das relevante ulimit erhöht habe. Da der Prozess zum Ändern von Ulimits für Docker-Container, die in Kubernetes ausgeführt werden, jedoch nicht ganz einfach zu finden ist, kann es jemand anderem helfen, die Details hier anzugeben.

  1. Aktualisieren Sie /etc/security/limits.conf um etwas wie
* - memlock unlimited
  1. /etc/docker/daemon.json um einzuschließen
"default-ulimits": { "memlock": { "name": "memlock", "hard": -1, "soft": -1 } }
  1. Starten Sie Docker/Kubernetes neu, bringen Sie Ihre Pods wieder hoch.

  2. Geben Sie einen laufenden Container ein und überprüfen Sie, ob das ulimit erhöht wurde:

$ kubectl exec -it pod-name -- /bin/sh
/ # ulimit -l
unlimited

Vielleicht kommen Sie mit etwas Subtilerem als dem _unbegrenzten_ Hammer davon; für mich schien eine Grenze von 128KiB (131072) zu funktionieren.

Dieses Problem tritt auch beim Versuch auf, ein Docker-Image für https://github.com/RTradeLtd/Temporal on go 1.14 zu erstellen

Und der Stapel häuft sich weiter. Sehen Sie, deshalb wurde ich am Anfang dieses Threads wütend (was ein schlimmer Fehler von meiner Seite war, stimme ich zu). Obwohl ich mir viel Mühe gegeben habe, zu erklären und zu reproduzieren, dass dies ein Blocker ist, wurde ich geschlossen, um die Veröffentlichung nicht zu stören. Auch nachdem klar war, dass es sich nicht um ein Docker-Problem handelt.

Jetzt befinden wir uns in einer viel schlechteren Situation, da verschiedene Projekte Go 1.14 auf die schwarze Liste setzen. Dieser Fehler soll derzeit nur in Go 1.15 behoben werden. Sind wir aufgrund der oben verlinkten Probleme zuversichtlich, dass es eine gute Idee ist, dies um 8 Monate zu verschieben? Ich denke, es wäre schön, das Durcheinander anzuerkennen und zu versuchen, es in einer Patch-Version zu beheben, und nicht darauf zu warten, dass weitere Projekte gebissen werden.

Ja, mir ist bewusst, dass ich die Leute hier nur nerve, anstatt es selbst zu reparieren. Es tut mir leid, dass ich keinen sinnvolleren Beitrag leisten kann, ich möchte nur das Ökosystem nicht fragmentieren. Go-Module waren bereits ein Schlag für viele Projekte, lassen Sie uns nicht mit einer weiteren Eigenart verdoppeln, die Tools beachten müssen.

Ian Lance-Taylor hat gesagt, dass der Fix zurückportiert wird, sobald es einen gibt: https://groups.google.com/d/msg/golang-dev/_FbRwBmfHOg/mmtMSjO1AQAJ

@lmb Oh das ist sehr schön zu hören, danke für den Link.

Zu Ihrer Information: Ubuntu 20.04 wird wahrscheinlich 5.4.0 ausliefern, was bedeutet, dass ab Ende nächsten Monats die
Die neuesten Ubuntu LTS und Golang funktionieren nicht sofort zusammen.

Lorenz Bauer [email protected] schrieb am Fr., 6. März 2020, 12:42:

Ian Lance-Taylor hat gesagt, dass der Fix zurückportiert wird, sobald er da ist
eine: https://groups.google.com/d/msg/golang-dev/_FbRwBmfHOg/mmtMSjO1AQAJ


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/golang/go/issues/37436?email_source=notifications&email_token=AAAO66R6S5VOWQBKETLI5UDRGDORJA5CNFSM4K3GBRRKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTP5WWZ
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAAO66SH6J4M75WDJ5GO7HTRGDORJANCNFSM4K3GBRRA
.

@karalabe so stark wie ich es aufbringen kann, du

Außerdem war ich der Erste, der bemerkte, dass das Problem von Ihrem Host-Kernel herrührt, nicht vom Docker-Modul. Sie haben nicht erwähnt, dass Sie auf Ubuntu sind, bis ich darauf hingewiesen habe.

Ich glaube, Sie schulden uns nach dieser Notiz noch eine weitere Entschuldigung.

BEARBEITEN: Ich habe Sie auch gebeten, die Goroutine-Stack-Traces (beginnend mit goroutine x [runnable] ) aus Ihrem Bericht zu entfernen, da sie das Lesen/Navigieren der Seite erschweren. [Update: Russ hat die Stacks herausgeschnitten.]

Denken Sie bitte daran, dass erfolgreiche Kommunikation schwer ist und eine Fähigkeit, die man üben muss. Emotionen können gegen uns arbeiten und unser Ziel einer erfolgreichen Kommunikation behindern, ich war selbst dort. Ja, es liegt ein Verstoß gegen den Verhaltenskodex vor und es ist gut, darauf hinzuweisen. Hilfreich ist auch eine freiwillige Entschuldigung. Lassen Sie uns nun versuchen, sicherzustellen, dass jeder Beitrag einen positiven Nettoeffekt auf die Zusammenarbeit und die Lösung dieses Problems hat.

@rtreffer Weißt du, ob die für Ubuntu

@rtreffer Weißt du, ob die für Ubuntu

Es wird im Release-Kernel für 20.04 enthalten sein, ja:

(master)mwhudson<strong i="9">@anduril</strong>:~/src/upstream/linux-2.6$ git log -1 --oneline ad9325e9870914b18b14857c154a0fee0bd77287
ad9325e98709 x86/fpu: Don't cache access to fpu_fpregs_owner_ctx
(master)mwhudson<strong i="10">@anduril</strong>:~/src/upstream/linux-2.6$ git tag --contains ad9325e9870914b18b14857c154a0fee0bd77287
Ubuntu-5.4-5.4.0-10.13
Ubuntu-5.4-5.4.0-11.14
Ubuntu-5.4-5.4.0-12.15
Ubuntu-5.4-5.4.0-13.16
Ubuntu-5.4-5.4.0-14.17
Ubuntu-5.4.0-15.18
Ubuntu-5.4.0-16.19
Ubuntu-5.4.0-17.20
Ubuntu-5.4.0-17.21
Ubuntu-5.4.0-8.11
Ubuntu-5.4.0-9.12
Ubuntu-raspi2-5.4-5.4.0-1002.2
Ubuntu-raspi2-5.4.0-1003.3
Ubuntu-raspi2-5.4.0-1004.4

Basierend auf Diskussionen mit @aclements , @dr2chase , @randall77 und anderen ist unser Plan für die Version 1.14.1:

  • eine Wiki-Seite schreiben, die das Problem beschreibt
  • weiterhin mlock auf einer Kernel-Version verwenden, die möglicherweise fehlerhaft ist
  • Wenn mlock fehlschlägt, notiere diese Tatsache still und fahre mit der Ausführung fort
  • Wenn wir ein unerwartetes SIGSEGV oder SIGBUS und mlock fehlgeschlagen ist, dann im Crash-Stack Trace Point Leute auf der Wiki-Seite

Die Hoffnung ist, dass dies eine gute Kombination aus einer korrekten Ausführung im Normalfall bietet und gleichzeitig die Leute auf potenziell fehlerhafte Kernel auf Informationen aufmerksam macht, die ihnen helfen zu entscheiden, ob das Problem ihr Kernel oder ihr Programm oder ein Fehler in Go selbst ist.

Dies kann auch mit besseren Versuchen kombiniert werden, anhand des Felds uname version zu erkennen, ob ein bestimmter Kernel gepatcht wurde (wir prüfen derzeit nur das Feld release ).

Eine andere Sache, die wir besprochen haben: Wenn ein mlock fehlgeschlagen ist und wir uns selbst ein Signal senden, berühren Sie zuerst den Signalstapel.

@ianlancetaylor das klingt nach einer tollen Idee!

Wenn Sie es noch nicht in Betracht gezogen haben: Link zu dieser Wiki-Seite von der Fehlermeldung (möglicherweise mit einer weiteren Umleitung)

ZB macht iPXE das über Links wie http://ipxe.org/1d0c6539 (ihre Ausgabe ist optimiert für Boot-ROMs, begrenzten Platz und dergleichen)

  • eine Wiki-Seite schreiben, die das Problem beschreibt

  • weiterhin mlock auf einer Kernel-Version verwenden, die möglicherweise fehlerhaft ist

  • Wenn mlock fehlschlägt, notiere diese Tatsache still und fahre mit der Ausführung fort

Wäre es nicht besser, auch die asynchrone Voreinstellung zu deaktivieren? Das Problem kann zwar auch bei asyncpreemptoff=1 auftreten, aber der Fehler war selten genug, dass ohne ihn monatelang niemand aufgefallen ist.

Gibt es eine Möglichkeit (außerhalb der Go-Laufzeit) zu testen, ob Ihr Kernel gepatcht ist? Wir pflegen unsere eigenen Kernel außerhalb der Distribution, wodurch dies sogar funktioniert.

@gopherbot bitte backport auf go1.14. Es ist ein ernstes Problem ohne Workaround.

Eröffnete(s) Backport-Problem(e): #37807 (für 1.14).

Denken Sie daran, die Cherry-Pick-CL(s) zu erstellen, sobald der Patch gemäß https://golang.org/wiki/MinorReleases an den Master

@nemith hier gibt es einen C-Reproduzierer: https://github.com/golang/go/issues/35326#issuecomment -558690446

@randall77 @aarzilli In Anbetracht dessen halte ich es eigentlich nicht für eine gute Idee, zusätzliche partielle Abschwächungen hinzuzufügen, wie das Berühren der Seite des Signalstapels oder das Deaktivieren der asynchronen Voreinstellung. Es handelt sich um einen Fehler auf Kernel-Ebene, der jedes Programm betreffen kann, das ein Signal empfängt. Leute, die mit einem fehlerhaften Kernel arbeiten, sollten den Kernel auf die eine oder andere Weise aktualisieren. Die Verwendung von mlock ist eine zuverlässige Abschwächung, die immer funktionieren sollte, und daher ist es vernünftig, es auszuprobieren. Das Berühren des Signalstapels vor dem Senden eines Preemption-Signals oder das vollständige Deaktivieren der Signalpreemption ist keine zuverlässige Abschwächung. Ich denke, wir sollten nicht auf eine unzuverlässige Minderung zurückgreifen; wir sollten dem Benutzer sagen, dass er den Kernel aktualisieren soll.

Leute, die den Kernel nicht aktualisieren können, haben die Möglichkeit, mit GODEBUG=asyncpreemptoff=1 , was eine ebenso effektive Teilminderung wie die anderen beiden ist.

Ich denke, wir sollten nicht auf eine unzuverlässige Minderung zurückgreifen; wir sollten dem Benutzer sagen, dass er den Kernel aktualisieren soll.

Ich würde dir zustimmen, wenn sich der Fehler immer in einem Absturz manifestieren würde. Aber das tut es nicht - es beschädigt nur zufällig den Speicher. Vielleicht stürzt es ab, aber vielleicht beschädigt es nur zufällig die Daten des Programms und läuft weiter. Ich denke, es ist unsere Pflicht, alle möglichen Maßnahmen zu ergreifen, um Datenbeschädigungen zu verhindern, auch wenn dies bedeutet, dass wir nicht so oft über das erforderliche Kernel-Upgrade berichten.

Es ist eine Jetzt-verspäter-Entscheidung. Wir können jetzt versuchen, eine Datenbeschädigung zu verhindern, indem wir die Signalseiten vor der Verwendung berühren. Oder wir können versuchen, später eine Beschädigung zu verhindern, indem wir den Benutzer im Falle eines Absturzes benachrichtigen. Wir können nicht beides wählen.

Ich wünschte, es gäbe eine Möglichkeit, eine Nachricht zu senden, wenn wir einen mlock-Fehler erkennen, ohne abzustürzen, und dies dann durch Berühren von Seiten abzuschwächen. Ich glaube nicht, dass das Go-Programm das auf stdout/stderr leider kann. Vielleicht könnten wir etwas in das Syslog werfen? Es würde nur denen helfen, die einen Blick auf das Syslog werfen, was wahrscheinlich nicht viele sind.

Gutes Argument.

Wie wäre es mit einer Nachricht zur Installation? Das bringt eine Änderung der Installationsprozeduren für Ihre Binärversionen und die der Distributionen mit sich, aber das würde Ihnen erlauben, den Reproduzierer auszuführen, um den Fehler endgültig zu testen.

@networkimprov Das ist eine gute Idee, aber da Leute kompilierte Programme über Maschinen senden, die unterschiedliche Kernel-Versionen haben, denke ich, dass wir auch den oben beschriebenen Ansatz brauchen.

Änderung https://golang.org/cl/223121 erwähnt dieses Problem: runtime: don't crash on mlock failure

Ich habe https://golang.org/cl/223121 gesendet

Nun, @randall77 / @ianlancetaylor , ich neige dazu, nicht zu Kernel- Fehler.

Als solches sollte es über Ihre Kernelpfade eskalieren.
Distributionen haben den Patch abgeholt und verschickt. Es wurde zurückportiert. Jede neue Installation erhält einen nicht betroffenen Kernel.
Wenn Sie Ihren eigenen Kernel rollen, müssen Sie diese Arbeit selbst erledigen. Wie gewöhnlich.

Seien Sie hilfreich für Benutzer, die es treffen, und seien Sie so hilfreich wie möglich.
Aber ich glaube nicht, dass es in der Verantwortung des Golang liegt, einen Kernel-Bug zu beheben oder Benutzer zu zwingen, den Patch anzuwenden.

@rtreffer Das ist, was wir versuchen: so hilfreich wie möglich sein.

Auf fehlerhaften Kerneln verhielten sich Go-Programme, die mit Go 1.14 erstellt wurden, unvorhersehbar und schlecht. Wir wollen das nicht einmal auf einem fehlerhaften Kernel tun. Wenn ein Programm einfach schnell und sauber scheitern würde, wäre das eine Sache. Was wir jedoch sahen, war eine Speicherbeschädigung, die zu unklaren Fehlern führte. Siehe unter anderem #35326.

Glaubst du, wir sollten etwas anderes tun als das, was wir jetzt tun?

@rtreffer Nun gut. Wir haben einige 5.2-Produktionskernel, die nicht betroffen sind, da sie nicht mit gcc9 kompiliert wurden, und wir könnten den Fix auch problemlos in unsere Kernel-Zeile patchen, ohne etwas anderes zu beeinflussen, und gut ist. Ein Kernel-Bug existiert in unserer Umgebung nicht und das Aktualisieren von Hauptversionen erfordert viel mehr Tests und eine sorgfältige Einführung in die gesamte Flotte, daher ist es keine gute Situation, einfach "Ihren Kernel zu aktualisieren".

Auf der anderen Seite hat uns die Problemumgehung basierend auf den Kernel-Versionsnummern dazu veranlasst, zu mlocks zu wechseln, die aufgrund von ulimit-Problemen fehlgeschlagen sind. Das ist kein Kernel-Bug.

Davon abgesehen bin ich mir nicht sicher, ob es hier eine bessere Lösung gibt und das Go-Team hat wahrscheinlich den richtigen Anruf getätigt.

@ianlancetaylor vielleicht könnten Sie den C-Reproduzierer in den Quell- und Binärversionen

Wie wäre es mit einer Nachricht zur Installation? Das bringt eine Änderung der Installationsprozeduren für Ihre Binärversionen und die der Distributionen mit sich, aber das würde Ihnen erlauben, den Reproduzierer auszuführen, um den Fehler endgültig zu testen.

Jede Distribution, die dem genügend Aufmerksamkeit schenkt, wird mit Sicherheit nur ihren Kernel patchen.

@ianlancetaylor Ich stimme dem weiteren Vorgehen

Ich wollte betonen, dass die Korruption nicht von Anfang an ein Fehler oder Fehler ist, und Distributionen liefern feste Kernel. Es sollte bereits verblassen.

Aus diesem Grund glaube ich nicht, dass mehr als die vorgeschlagenen Hinweise (Wiki + Panik) erforderlich sind.

@rtreffer Super , danke.

Änderung https://golang.org/cl/223417 erwähnt dieses Problem: [release-branch.go1.14]runtime: don't crash on mlock failure

Nur um klarzustellen, dass das Programm anfällig für Speicherbeschädigungen ist, wenn mlock auf 1.14.1 fehlschlägt, basierend auf dem, was das Wiki sagt?

Danke

@smasher164 Nicht unbedingt. Wir drucken die Meldung "mlock fehlgeschlagen" nicht mehr, wenn der mlock-Aufruf fehlschlägt. Stattdessen speichern wir nur die Tatsache, dass es fehlgeschlagen ist. wenn Ihr Programm abstürzt, geben wir die Tatsache, dass der mlock fehlgeschlagen ist, im Fehlertext aus. Was bedeutet: "Wir denken, dass Ihr Kernel fehlerhaft sein könnte. Wir haben den mlock-Workaround versucht, und er ist fehlgeschlagen. Wir haben Ihr Programm trotzdem ausgeführt und es ist am Ende abgestürzt." Vielleicht lag es am Kernel-Bug, vielleicht ist es nur ein Fehler in Ihrem Programm.

@randall77 Danke für die Antwort. Kann man also mit Sicherheit sagen, dass, wenn mlock fehlgeschlagen ist und das Programm beim Berühren des Stack vor dem Senden eines Preemption-Signals nicht abstürzt, keine asynchrone Preemption-bezogene Speicherbeschädigung im Programm existiert?

Leider nicht. Wenn mlock fehlschlägt und Sie einen fehlerhaften Kernel haben, kann eine Speicherbeschädigung auftreten. Nur weil das Programm nicht abstürzt, heißt das nicht, dass es nicht irgendwo eine Beschädigung gab. Ein Absturz ist ein Nebeneffekt der Speicherbeschädigung - nur das Fehlschlagen von mlock führt nicht zu einem Absturz. (Wir haben das in 1.14 gemacht. Das ist eines der Dinge, die wir für 1.14.1 geändert haben.)
Selbst wenn Sie die asynchrone Voreinstellung deaktivieren, kann es dennoch zu einer Speicherbeschädigung kommen. Nur mit einer geringeren Rate, da Ihr Programm wahrscheinlich noch andere Signale (Timer usw.) erhält.

@smasher164 Lassen Sie es uns wissen, wenn Sie die Wiki-Seite https://golang.org/wiki/LinuxKernelSignalVectorBug für unklar halten. Danke.

Wie kann ich dies deaktivieren?

Ich bin in einem unprivilegierten lxc Behälter durch lxd erstellt , so dass er den gleichen Kernel wie die Host hat , aber zu Satz systemweite Grenzen nicht in der Lage:

# container
$ uname -a
Linux runner-33-project-447-concurrent-0-job-25150 5.4.0-31-generic #35-Ubuntu SMP Thu May 7 20:20:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ /proc/version_signature
/proc/version_signature: Permission denied
$ ulimit -l 123456
ulimit: max locked memory: cannot modify limit: Operation not permitted
# host
$ uname -a
Linux gitlab-ci-runner-lxd-2 5.4.0-31-generic #35-Ubuntu SMP Thu May 7 20:20:34 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ cat /proc/version_signature 
Ubuntu 5.4.0-31.35-generic 5.4.34

Laut https://github.com/golang/go/issues/37436#issuecomment -595836976 enthält der Host (focal) den Kernel-Patch.

Go wurde vor ein paar Tagen mit go get golang.org/dl/go1.14 und go1.14 download

$ go version
go version go1.14 linux/amd64

Nochmals: Wie kann ich dies deaktivieren?

Ich kann/will die systemweiten Grenzen vielleicht nicht ändern, da andere Programme/Pipelines betroffen sind und ein kollektiver Konsens für all diese Möglichkeiten gefunden werden muss, bevor systemweite Optionen geändert werden.

Es ist gut, dass wir eine solche Erkennung hatten, aber es ist kaputt, dass wir uns nicht einfach abmelden können. Wenn wir wissen, haben die Kernel die festen Patches und die Erkennung ist anfällig für Fehlalarme.

@dionysius Dies wurde in 1.14.1 behoben, wie in https://github.com/golang/go/issues/37436#issuecomment -597360484 beschrieben. Ich glaube, Sie müssen auf eine neuere Version von go upgraden: https://godoc.org/golang.org/dl/go1.14.2.

Ich werde versuchen, dann explizit die Go-Version zu laden, ich habe erwartet, dass go get golang.org/dl/go1.14 die neueste Version 1.14 lädt. Werde mich wieder melden.

Bearbeiten, anscheinend ist 1.14.3 die neueste Version 1.14 von heute

Update: sieht gut aus mit go get golang.org/dl/go1.14.3 , unerwartet, dass ohne Patch, der nicht die neuesten lädt, gut zu wissen (sonst wäre ich nie in dieses Problem geraten)

Nur ein Hinweis - Go1.15 steht kurz vor der Veröffentlichung, und eine Beta wurde bereits veröffentlicht, aber der temporäre Patch wurde noch nicht entfernt (Es gibt Todo-Kommentare, die bei Go1.15 entfernt werden müssen).

Ich denke, es ist wichtig, den Workaround zu entfernen, da Ubuntu 20.04 LTS einen gepatchten 5.4.0-Kernel verwendet. Dies bedeutet, dass jeder Benutzer unter Ubuntu 20.04 immer noch unnötig Seiten sperrt, und wenn er in einem Docker-Container ausgeführt wird, wird diese Warnung bei jedem Absturz angezeigt, ungeachtet der Tatsache, dass sein Kernel nicht wirklich fehlerhaft ist. Diese Benutzer könnten also auf eine wilde Jagd geschickt werden, um all diese Informationen zu verstehen und zu lesen, und es hat nichts mit ihrem Fehler zu tun, wahrscheinlich für den gesamten Lebenszyklus von Ubuntu 20.04.

@DanielShaulov danke. Könntest du dafür eine neue Ausgabe eröffnen? Dieser bezieht sich auf das Problem in 1.14.

@networkimprov sicher: #40184

Änderung https://golang.org/cl/243658 erwähnt dieses Problem: runtime: let GODEBUG=mlock=0 disable mlock calls

Änderung https://golang.org/cl/244059 erwähnt dieses Problem: runtime: don't mlock on Ubuntu 5.4 systems

Wann wird go1.14.7 mit dieser Modifikation veröffentlicht?

Der Fix ist in jeder Version seit 1.14.1 enthalten, die vor Monaten ausgeliefert wurde.

Änderung https://golang.org/cl/246200 erwähnt dieses Problem: runtime: revert signal stack mlocking

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen