github.com/pingcap/failpoint@v0.0.0-20240412033321-fd0796e60f86/terms.go (about) 1 // Copyright 2019 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Copyright 2016 CoreOS, Inc. 16 // 17 // Licensed under the Apache License, Version 2.0 (the "License"); 18 // you may not use this file except in compliance with the License. 19 // You may obtain a copy of the License at 20 // 21 // http://www.apache.org/licenses/LICENSE-2.0 22 // 23 // Unless required by applicable law or agreed to in writing, software 24 // distributed under the License is distributed on an "AS IS" BASIS, 25 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 // See the License for the specific language governing permissions and 27 // limitations under the License. 28 29 package failpoint 30 31 import ( 32 "fmt" 33 "math/rand" 34 "os" 35 "os/exec" 36 "strings" 37 "sync" 38 "time" 39 ) 40 41 func init() { 42 rand.Seed(time.Now().Unix()) 43 } 44 45 // terms encodes the state for a failpoint term string (see fail(9) for examples) 46 // <fp> :: <term> ( "->" <term> )* 47 type terms struct { 48 // chain is a slice of all the terms from desc 49 chain []*term 50 // desc is the full term given for the failpoint 51 desc string 52 // mu protects the state of the terms chain 53 mu sync.Mutex 54 } 55 56 // term is an executable unit of the failpoint terms chain 57 type term struct { 58 desc string 59 60 mods mod 61 act actFunc 62 val interface{} 63 64 parent *terms 65 fp *Failpoint 66 } 67 68 type mod interface { 69 allow() bool 70 } 71 72 type modCount struct{ c int } 73 74 func (mc *modCount) allow() bool { 75 if mc.c > 0 { 76 mc.c-- 77 return true 78 } 79 return false 80 } 81 82 type modProb struct{ p float64 } 83 84 func (mp *modProb) allow() bool { return rand.Float64() <= mp.p } 85 86 type modList struct{ l []mod } 87 88 func (ml *modList) allow() bool { 89 for _, m := range ml.l { 90 if !m.allow() { 91 return false 92 } 93 } 94 return true 95 } 96 97 func newTerms(desc string, fp *Failpoint) (*terms, error) { 98 chain, err := parse(desc, fp) 99 if err != nil { 100 return nil, err 101 } 102 t := &terms{chain: chain, desc: desc} 103 for _, c := range chain { 104 c.parent = t 105 } 106 return t, nil 107 } 108 109 func (t *terms) String() string { return t.desc } 110 111 func (t *terms) eval() (Value, error) { 112 t.mu.Lock() 113 defer t.mu.Unlock() 114 for _, term := range t.chain { 115 if term.mods.allow() { 116 return term.do() 117 } 118 } 119 return nil, ErrNotAllowed 120 } 121 122 // split terms from a -> b -> ... into [a, b, ...] 123 func parse(desc string, fp *Failpoint) (chain []*term, err error) { 124 origDesc := desc 125 for len(desc) != 0 { 126 t := parseTerm(desc, fp) 127 if t == nil { 128 return nil, fmt.Errorf("failpoint: failed to parse %q past %q", origDesc, desc) 129 } 130 desc = desc[len(t.desc):] 131 chain = append(chain, t) 132 if len(desc) >= 2 { 133 if !strings.HasPrefix(desc, "->") { 134 return nil, fmt.Errorf("failpoint: failed to parse %q past %q, expected \"->\"", origDesc, desc) 135 } 136 desc = desc[2:] 137 } 138 } 139 return chain, nil 140 } 141 142 // <term> :: <mod> <act> [ "(" <val> ")" ] 143 func parseTerm(desc string, fp *Failpoint) *term { 144 t := &term{} 145 modStr, mods := parseMod(desc) 146 t.mods = &modList{mods} 147 actStr, act := parseAct(desc[len(modStr):]) 148 t.act = act 149 valStr, val := parseVal(desc[len(modStr)+len(actStr):]) 150 t.val = val 151 t.desc = desc[:len(modStr)+len(actStr)+len(valStr)] 152 t.fp = fp 153 if len(t.desc) == 0 { 154 return nil 155 } 156 return t 157 } 158 159 // <mod> :: ((<float>|<int> "%")|(<int> "*" ))* 160 func parseMod(desc string) (ret string, mods []mod) { 161 applyPercent := func(s string, v float64) { 162 ret = ret + desc[:len(s)+1] 163 mods = append(mods, &modProb{v / 100.0}) 164 desc = desc[len(s)+1:] 165 } 166 applyCount := func(s string, v int) { 167 ret = ret + desc[:len(s)+1] 168 mods = append(mods, &modCount{v}) 169 desc = desc[len(s)+1:] 170 } 171 for { 172 s, v := parseIntFloat(desc) 173 if len(s) == 0 { 174 break 175 } 176 if len(s) == len(desc) { 177 return "", nil 178 } 179 switch v := v.(type) { 180 case float64: 181 if desc[len(s)] != '%' { 182 return "", nil 183 } 184 applyPercent(s, v) 185 case int: 186 switch desc[len(s)] { 187 case '%': 188 applyPercent(s, float64(v)) 189 case '*': 190 applyCount(s, v) 191 default: 192 return "", nil 193 } 194 default: 195 panic("???") 196 } 197 } 198 return ret, mods 199 } 200 201 // parseIntFloat parses an int or float from a string and returns the string 202 // it parsed it from (unlike scanf). 203 func parseIntFloat(desc string) (string, interface{}) { 204 // parse for ints 205 i := 0 206 for i < len(desc) { 207 if desc[i] < '0' || desc[i] > '9' { 208 break 209 } 210 i++ 211 } 212 if i == 0 { 213 return "", nil 214 } 215 216 intVal := int(0) 217 _, err := fmt.Sscanf(desc[:i], "%d", &intVal) 218 if err != nil { 219 return "", nil 220 } 221 if len(desc) == i { 222 return desc[:i], intVal 223 } 224 if desc[i] != '.' { 225 return desc[:i], intVal 226 } 227 228 // parse for floats 229 i++ 230 if i == len(desc) { 231 return desc[:i], float64(intVal) 232 } 233 234 j := i 235 for i < len(desc) { 236 if desc[i] < '0' || desc[i] > '9' { 237 break 238 } 239 i++ 240 } 241 if j == i { 242 return desc[:i], float64(intVal) 243 } 244 245 f := float64(0) 246 if _, err = fmt.Sscanf(desc[:i], "%f", &f); err != nil { 247 return "", nil 248 } 249 return desc[:i], f 250 } 251 252 // parseAct parses an action 253 // <act> :: "off" | "return" | "sleep" | "panic" | "break" | "print" | "pause" 254 func parseAct(desc string) (string, actFunc) { 255 for k, v := range actMap { 256 if strings.HasPrefix(desc, k) { 257 return k, v 258 } 259 } 260 return "", nil 261 } 262 263 // <val> :: <int> | <string> | <bool> | <nothing> 264 func parseVal(desc string) (string, interface{}) { 265 // return => struct{} 266 if len(desc) == 0 { 267 return "", struct{}{} 268 } 269 // malformed 270 if len(desc) == 1 || desc[0] != '(' { 271 return "", nil 272 } 273 // return() => struct{} 274 if desc[1] == ')' { 275 return "()", struct{}{} 276 } 277 // return("s") => string 278 s := "" 279 n, err := fmt.Sscanf(desc[1:], "%q", &s) 280 if n == 1 && err == nil { 281 return desc[:len(s)+4], s 282 } 283 // return(1) => int 284 v := 0 285 n, err = fmt.Sscanf(desc[1:], "%d", &v) 286 if n == 1 && err == nil { 287 return desc[:len(fmt.Sprintf("%d", v))+2], v 288 } 289 // return(true) => bool 290 b := false 291 n, err = fmt.Sscanf(desc[1:], "%t", &b) 292 if n == 1 && err == nil { 293 return desc[:len(fmt.Sprintf("%t", b))+2], b 294 } 295 // unknown type; malformed input? 296 return "", nil 297 } 298 299 type actFunc func(*term) (interface{}, error) 300 301 var actMap = map[string]actFunc{ 302 "off": actOff, 303 "return": actReturn, 304 "sleep": actSleep, 305 "panic": actPanic, 306 "break": actBreak, 307 "print": actPrint, 308 "pause": actPause, 309 } 310 311 func (t *term) do() (interface{}, error) { return t.act(t) } 312 313 func actOff(t *term) (interface{}, error) { return nil, nil } 314 315 func actReturn(t *term) (interface{}, error) { return t.val, nil } 316 317 func actSleep(t *term) (interface{}, error) { 318 var dur time.Duration 319 switch v := t.val.(type) { 320 case int: 321 dur = time.Duration(v) * time.Millisecond 322 case string: 323 vDur, err := time.ParseDuration(v) 324 if err != nil { 325 return nil, fmt.Errorf("failpoint: could not parse sleep(%v)", v) 326 } 327 dur = vDur 328 default: 329 return nil, fmt.Errorf("failpoint: ignoring sleep(%v)", v) 330 } 331 time.Sleep(dur) 332 return nil, nil 333 } 334 335 func actPause(t *term) (interface{}, error) { 336 if t.fp != nil { 337 t.fp.Pause() 338 } 339 return nil, nil 340 } 341 342 func actPanic(t *term) (interface{}, error) { 343 if t.val != nil { 344 panic(fmt.Sprintf("failpoint panic: %v", t.val)) 345 } 346 panic("failpoint panic") 347 } 348 349 func actBreak(t *term) (interface{}, error) { 350 p, perr := exec.LookPath(os.Args[0]) 351 if perr != nil { 352 panic(perr) 353 } 354 cmd := exec.Command("gdb", p, fmt.Sprintf("%d", os.Getpid())) 355 cmd.Stdin = os.Stdin 356 cmd.Stdout = os.Stdout 357 cmd.Stderr = os.Stderr 358 if err := cmd.Start(); err != nil { 359 panic(err) 360 } 361 362 // wait for gdb prompt 363 // XXX: tried doing this by piping stdout here and waiting on "(gdb) " 364 // but the the output won't appear since the process is STOPed and 365 // can't copy it back to the actual stdout 366 time.Sleep(3 * time.Second) 367 368 // don't zombie gdb 369 go cmd.Wait() 370 return nil, nil 371 } 372 373 func actPrint(t *term) (interface{}, error) { 374 fmt.Println("failpoint print:", t.val) 375 return nil, nil 376 }