Skip to content

os/signal: deadlock combining signal handling with syscall.AllThreadsSyscall #43149

@AndrewGMorgan

Description

@AndrewGMorgan

What version of Go are you using (go version)?

HEAD (of 1.16 development branch)

Does this issue reproduce with the latest release?

No. It is a failure introduced with the new syscall.AllThreadsSyscall*() functions.

What operating system and processor architecture are you using (go env)?

All linux builds - with CGO_ENABLED=0

What did you do?

Following this bug: https://bugzilla.kernel.org/show_bug.cgi?id=210533 (which did not relate to the golang sources) I tried to test signal handling with the new (post 1.15) syscall.AllThreadsSyscall*() by adding the following test to the golang tree:

$ cat os/signal/signal_linux_test.go 
// +build linux

package signal

import (
        "os"
        "syscall"
        "testing"
        "time"
)

const prSetKeepCaps = 8

func TestAllThreadsSyscallSignals(t *testing.T) {
        if _, _, err := syscall.AllThreadsSyscall(syscall.SYS_PRCTL, prSetKeepCaps, 0, 0); err == syscall.ENOTSUP {
                t.Skip("AllThreadsSyscall disabled with cgo")
        }

        sig := make(chan os.Signal, 1)
        Notify(sig, os.Interrupt)

        for i := 0; i <= 100; i++ {
                if _, _, errno := syscall.AllThreadsSyscall(syscall.SYS_PRCTL, prSetKeepCaps, uintptr(i&1), 0); errno != 0 {
                        t.Fatalf("[%d] failed to set KEEP_CAPS=%d: %v", i, i&1, errno)
                }
        }

        select {
        case <-time.After(10 * time.Millisecond):
        case <-sig:
                t.Fatal("unexpected signal")
        }
        Stop(sig)
        close(sig)
}

Then in a build tree with this added test case I built and ran it as follows:

$ CGO_ENABLED=0 ../bin/go test -c os/signal
$ ./signal.test -test.v=1

What did you expect to see?

$ ./signal.test -test.v=1
=== RUN   TestAllThreadsSyscallSignals
--- PASS: TestAllThreadsSyscallSignals (0.02s)
=== RUN   TestSignal
    signal_test.go:116: sighup...
    signal_test.go:127: sigwinch...
    signal_test.go:134: sighup...
    signal_test.go:137: sighup...
--- PASS: TestSignal (0.00s)
=== RUN   TestStress
<...all good beyond here...>

What did you see instead?

$ ./signal.test -test.v=1
=== RUN   TestAllThreadsSyscallSignals
<...hangs here...>

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions