Source file src/runtime/testdata/testprog/stw_mexit.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "runtime" 9 ) 10 11 func init() { 12 register("mexitSTW", mexitSTW) 13 } 14 15 // Stress test for pp.oldm pointing to an exited M. 16 // 17 // If pp.oldm points to an exited M it should be ignored and another M used 18 // instead. To stress: 19 // 20 // 1. Start and exit many threads (thus setting oldm on some P). 21 // 2. Meanwhile, frequently stop the world. 22 // 23 // If procresize incorrect attempts to assign a P to an exited M, likely 24 // failure modes are: 25 // 26 // 1. Crash in startTheWorldWithSema attempting to access the M, if it is nil. 27 // 28 // 2. Memory corruption elsewhere after startTheWorldWithSema writes to the M, 29 // if it is not nil, but is freed and reused for another allocation. 30 // 31 // 3. Hang on a subsequent stop the world waiting for the P to stop, if the M 32 // object is valid, but the M is exited, because startTheWorldWithSema didn't 33 // actually wake anything to run the P. The P is _Pidle, but not in the pidle 34 // list, thus startTheWorldWithSema will wake for it to actively stop. 35 // 36 // For this to go wrong, an exited M must fail to clear mp.self and must leave 37 // the M on the sched.midle list. 38 // 39 // Similar to TraceSTW. 40 func mexitSTW() { 41 // Ensure we have multiple Ps, but not too many, as we want the 42 // runnable goroutines likely to run on Ps with oldm set. 43 runtime.GOMAXPROCS(4) 44 45 // Background busy work so there is always something runnable. 46 for i := range 2 { 47 go traceSTWTarget(i) 48 } 49 50 // Wait for children to start running. 51 ping.Store(1) 52 for pong[0].Load() != 1 {} 53 for pong[1].Load() != 1 {} 54 55 for range 100 { 56 // Exit a thread. The last P to run this will have it in oldm. 57 go func() { 58 runtime.LockOSThread() 59 }() 60 61 // STW 62 var ms runtime.MemStats 63 runtime.ReadMemStats(&ms) 64 } 65 66 stop.Store(true) 67 68 println("OK") 69 } 70