| | |
| | |
| | |
| |
|
| | |
| |
|
| | |
| | |
| |
|
| | package runtime_test |
| |
|
| | import ( |
| | "internal/abi" |
| | "internal/runtime/atomic" |
| | "internal/testenv" |
| | "os" |
| | "os/exec" |
| | "runtime" |
| | "strings" |
| | "testing" |
| | "time" |
| | ) |
| |
|
| | var regConfirmRun atomic.Int32 |
| |
|
| | |
| | func regFinalizerPointer(v *TintPointer) (int, float32, [10]byte) { |
| | regConfirmRun.Store(int32(*(*int)(v.p))) |
| | return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} |
| | } |
| |
|
| | |
| | func regFinalizerIface(v Tinter) (int, float32, [10]byte) { |
| | regConfirmRun.Store(int32(*(*int)(v.(*TintPointer).p))) |
| | return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} |
| | } |
| |
|
| | |
| | |
| | type TintPointer struct { |
| | p *Tint |
| | } |
| |
|
| | func (*TintPointer) m() {} |
| |
|
| | func TestFinalizerRegisterABI(t *testing.T) { |
| | |
| | |
| | if os.Getenv("TEST_FINALIZER_REGABI") != "1" { |
| | cmd := testenv.CleanCmdEnv(exec.Command(testenv.Executable(t), "-test.run=^TestFinalizerRegisterABI$", "-test.v")) |
| | cmd.Env = append(cmd.Env, "TEST_FINALIZER_REGABI=1") |
| | out, err := cmd.CombinedOutput() |
| | if !strings.Contains(string(out), "PASS\n") || err != nil { |
| | t.Fatalf("%s\n(exit status %v)", string(out), err) |
| | } |
| | return |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | runtime.GC() |
| | runtime.GC() |
| |
|
| | |
| | runtime.SetFinalizer(new(TintPointer), func(_ *TintPointer) {}) |
| |
|
| | |
| | |
| | success := false |
| | for i := 0; i < 100; i++ { |
| | if runtime.FinalizerGAsleep() { |
| | success = true |
| | break |
| | } |
| | time.Sleep(20 * time.Millisecond) |
| | } |
| | if !success { |
| | t.Fatal("finalizer not asleep?") |
| | } |
| |
|
| | argRegsBefore := runtime.SetIntArgRegs(abi.IntArgRegs) |
| | defer runtime.SetIntArgRegs(argRegsBefore) |
| |
|
| | tests := []struct { |
| | name string |
| | fin any |
| | confirmValue int |
| | }{ |
| | {"Pointer", regFinalizerPointer, -1}, |
| | {"Interface", regFinalizerIface, -2}, |
| | } |
| | for i := range tests { |
| | test := &tests[i] |
| | t.Run(test.name, func(t *testing.T) { |
| | x := &TintPointer{p: new(Tint)} |
| | *x.p = (Tint)(test.confirmValue) |
| | runtime.SetFinalizer(x, test.fin) |
| |
|
| | runtime.KeepAlive(x) |
| |
|
| | |
| | runtime.GC() |
| | runtime.GC() |
| |
|
| | if !runtime.BlockUntilEmptyFinalizerQueue(int64(time.Second)) { |
| | t.Fatal("finalizer failed to execute") |
| | } |
| | if got := int(regConfirmRun.Load()); got != test.confirmValue { |
| | t.Fatalf("wrong finalizer executed? got %d, want %d", got, test.confirmValue) |
| | } |
| | }) |
| | } |
| | } |
| |
|