get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/signal_test.go (about) 1 // Copyright 2012-2019 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //go:build !windows 15 // +build !windows 16 17 package server 18 19 import ( 20 "errors" 21 "fmt" 22 "os" 23 "os/exec" 24 "path/filepath" 25 "strings" 26 "syscall" 27 "testing" 28 "time" 29 30 "get.pme.sh/pnats/logger" 31 "github.com/nats-io/nats.go" 32 ) 33 34 func TestSignalToReOpenLogFile(t *testing.T) { 35 logFile := filepath.Join(t.TempDir(), "test.log") 36 opts := &Options{ 37 Host: "127.0.0.1", 38 Port: -1, 39 NoSigs: false, 40 LogFile: logFile, 41 } 42 s := RunServer(opts) 43 defer s.SetLogger(nil, false, false) 44 defer s.Shutdown() 45 46 // Set the file log 47 fileLog := logger.NewFileLogger(s.opts.LogFile, s.opts.Logtime, s.opts.Debug, s.opts.Trace, true, logger.LogUTC(s.opts.LogtimeUTC)) 48 s.SetLogger(fileLog, false, false) 49 50 // Add a trace 51 expectedStr := "This is a Notice" 52 s.Noticef(expectedStr) 53 buf, err := os.ReadFile(logFile) 54 if err != nil { 55 t.Fatalf("Error reading file: %v", err) 56 } 57 if !strings.Contains(string(buf), expectedStr) { 58 t.Fatalf("Expected log to contain %q, got %q", expectedStr, string(buf)) 59 } 60 // Rename the file 61 if err := os.Rename(logFile, logFile+".bak"); err != nil { 62 t.Fatalf("Unable to rename file: %v", err) 63 } 64 // This should cause file to be reopened. 65 syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) 66 // Wait a bit for action to be performed 67 time.Sleep(500 * time.Millisecond) 68 buf, err = os.ReadFile(logFile) 69 if err != nil { 70 t.Fatalf("Error reading file: %v", err) 71 } 72 expectedStr = "File log re-opened" 73 if !strings.Contains(string(buf), expectedStr) { 74 t.Fatalf("Expected log to contain %q, got %q", expectedStr, string(buf)) 75 } 76 } 77 78 func TestSignalToReloadConfig(t *testing.T) { 79 opts, err := ProcessConfigFile("./configs/reload/basic.conf") 80 if err != nil { 81 t.Fatalf("Error processing config file: %v", err) 82 } 83 opts.NoLog = true 84 s := RunServer(opts) 85 defer s.Shutdown() 86 87 // Repeat test to make sure that server services signals more than once... 88 for i := 0; i < 2; i++ { 89 loaded := s.ConfigTime() 90 91 // Wait a bit to ensure ConfigTime changes. 92 time.Sleep(5 * time.Millisecond) 93 94 // This should cause config to be reloaded. 95 syscall.Kill(syscall.Getpid(), syscall.SIGHUP) 96 // Wait a bit for action to be performed 97 time.Sleep(500 * time.Millisecond) 98 99 if reloaded := s.ConfigTime(); !reloaded.After(loaded) { 100 t.Fatalf("ConfigTime is incorrect.\nexpected greater than: %s\ngot: %s", loaded, reloaded) 101 } 102 } 103 } 104 105 func TestProcessSignalNoProcesses(t *testing.T) { 106 pgrepBefore := pgrep 107 pgrep = func() ([]byte, error) { 108 return nil, &exec.ExitError{} 109 } 110 defer func() { 111 pgrep = pgrepBefore 112 }() 113 114 err := ProcessSignal(CommandStop, "") 115 if err == nil { 116 t.Fatal("Expected error") 117 } 118 expectedStr := "no nats-server processes running" 119 if err.Error() != expectedStr { 120 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 121 } 122 } 123 124 func TestProcessSignalMultipleProcesses(t *testing.T) { 125 pid := os.Getpid() 126 pgrepBefore := pgrep 127 pgrep = func() ([]byte, error) { 128 return []byte(fmt.Sprintf("123\n456\n%d\n", pid)), nil 129 } 130 defer func() { 131 pgrep = pgrepBefore 132 }() 133 134 err := ProcessSignal(CommandStop, "") 135 if err == nil { 136 t.Fatal("Expected error") 137 } 138 expectedStr := "multiple nats-server processes running:\n123\n456" 139 if err.Error() != expectedStr { 140 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 141 } 142 } 143 144 func TestProcessSignalMultipleProcessesGlob(t *testing.T) { 145 pid := os.Getpid() 146 pgrepBefore := pgrep 147 pgrep = func() ([]byte, error) { 148 return []byte(fmt.Sprintf("123\n456\n%d\n", pid)), nil 149 } 150 defer func() { 151 pgrep = pgrepBefore 152 }() 153 154 err := ProcessSignal(CommandStop, "*") 155 if err == nil { 156 t.Fatal("Expected error") 157 } 158 expectedStr := "\nsignal \"stop\" 123: no such process" 159 expectedStr += "\nsignal \"stop\" 456: no such process" 160 if err.Error() != expectedStr { 161 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 162 } 163 } 164 165 func TestProcessSignalMultipleProcessesGlobPartial(t *testing.T) { 166 pid := os.Getpid() 167 pgrepBefore := pgrep 168 pgrep = func() ([]byte, error) { 169 return []byte(fmt.Sprintf("123\n124\n456\n%d\n", pid)), nil 170 } 171 defer func() { 172 pgrep = pgrepBefore 173 }() 174 175 err := ProcessSignal(CommandStop, "12*") 176 if err == nil { 177 t.Fatal("Expected error") 178 } 179 expectedStr := "\nsignal \"stop\" 123: no such process" 180 expectedStr += "\nsignal \"stop\" 124: no such process" 181 if err.Error() != expectedStr { 182 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 183 } 184 } 185 186 func TestProcessSignalPgrepError(t *testing.T) { 187 pgrepBefore := pgrep 188 pgrep = func() ([]byte, error) { 189 return nil, errors.New("error") 190 } 191 defer func() { 192 pgrep = pgrepBefore 193 }() 194 195 err := ProcessSignal(CommandStop, "") 196 if err == nil { 197 t.Fatal("Expected error") 198 } 199 expectedStr := "unable to resolve pid, try providing one" 200 if err.Error() != expectedStr { 201 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 202 } 203 } 204 205 func TestProcessSignalPgrepMangled(t *testing.T) { 206 pgrepBefore := pgrep 207 pgrep = func() ([]byte, error) { 208 return []byte("12x"), nil 209 } 210 defer func() { 211 pgrep = pgrepBefore 212 }() 213 214 err := ProcessSignal(CommandStop, "") 215 if err == nil { 216 t.Fatal("Expected error") 217 } 218 expectedStr := "unable to resolve pid, try providing one" 219 if err.Error() != expectedStr { 220 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 221 } 222 } 223 224 func TestProcessSignalResolveSingleProcess(t *testing.T) { 225 pid := os.Getpid() 226 pgrepBefore := pgrep 227 pgrep = func() ([]byte, error) { 228 return []byte(fmt.Sprintf("123\n%d\n", pid)), nil 229 } 230 defer func() { 231 pgrep = pgrepBefore 232 }() 233 killBefore := kill 234 called := false 235 kill = func(pid int, signal syscall.Signal) error { 236 called = true 237 if pid != 123 { 238 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 239 } 240 if signal != syscall.SIGKILL { 241 t.Fatalf("signal is incorrect.\nexpected: killed\ngot: %v", signal) 242 } 243 return nil 244 } 245 defer func() { 246 kill = killBefore 247 }() 248 249 if err := ProcessSignal(CommandStop, ""); err != nil { 250 t.Fatalf("ProcessSignal failed: %v", err) 251 } 252 253 if !called { 254 t.Fatal("Expected kill to be called") 255 } 256 } 257 258 func TestProcessSignalInvalidCommand(t *testing.T) { 259 err := ProcessSignal(Command("invalid"), "123") 260 if err == nil { 261 t.Fatal("Expected error") 262 } 263 expectedStr := "unknown signal \"invalid\"" 264 if err.Error() != expectedStr { 265 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 266 } 267 } 268 269 func TestProcessSignalInvalidPid(t *testing.T) { 270 err := ProcessSignal(CommandStop, "abc") 271 if err == nil { 272 t.Fatal("Expected error") 273 } 274 expectedStr := "invalid pid: abc" 275 if err.Error() != expectedStr { 276 t.Fatalf("Error is incorrect.\nexpected: %s\ngot: %s", expectedStr, err.Error()) 277 } 278 } 279 280 func TestProcessSignalQuitProcess(t *testing.T) { 281 killBefore := kill 282 called := false 283 kill = func(pid int, signal syscall.Signal) error { 284 called = true 285 if pid != 123 { 286 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 287 } 288 if signal != syscall.SIGINT { 289 t.Fatalf("signal is incorrect.\nexpected: interrupt\ngot: %v", signal) 290 } 291 return nil 292 } 293 defer func() { 294 kill = killBefore 295 }() 296 297 if err := ProcessSignal(CommandQuit, "123"); err != nil { 298 t.Fatalf("ProcessSignal failed: %v", err) 299 } 300 301 if !called { 302 t.Fatal("Expected kill to be called") 303 } 304 } 305 306 func TestProcessSignalTermProcess(t *testing.T) { 307 killBefore := kill 308 called := false 309 kill = func(pid int, signal syscall.Signal) error { 310 called = true 311 if pid != 123 { 312 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 313 } 314 if signal != syscall.SIGTERM { 315 t.Fatalf("signal is incorrect.\nexpected: interrupt\ngot: %v", signal) 316 } 317 return nil 318 } 319 defer func() { 320 kill = killBefore 321 }() 322 323 if err := ProcessSignal(commandTerm, "123"); err != nil { 324 t.Fatalf("ProcessSignal failed: %v", err) 325 } 326 327 if !called { 328 t.Fatal("Expected kill to be called") 329 } 330 } 331 332 func TestProcessSignalReopenProcess(t *testing.T) { 333 killBefore := kill 334 called := false 335 kill = func(pid int, signal syscall.Signal) error { 336 called = true 337 if pid != 123 { 338 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 339 } 340 if signal != syscall.SIGUSR1 { 341 t.Fatalf("signal is incorrect.\nexpected: user defined signal 1\ngot: %v", signal) 342 } 343 return nil 344 } 345 defer func() { 346 kill = killBefore 347 }() 348 349 if err := ProcessSignal(CommandReopen, "123"); err != nil { 350 t.Fatalf("ProcessSignal failed: %v", err) 351 } 352 353 if !called { 354 t.Fatal("Expected kill to be called") 355 } 356 } 357 358 func TestProcessSignalReloadProcess(t *testing.T) { 359 killBefore := kill 360 called := false 361 kill = func(pid int, signal syscall.Signal) error { 362 called = true 363 if pid != 123 { 364 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 365 } 366 if signal != syscall.SIGHUP { 367 t.Fatalf("signal is incorrect.\nexpected: hangup\ngot: %v", signal) 368 } 369 return nil 370 } 371 defer func() { 372 kill = killBefore 373 }() 374 375 if err := ProcessSignal(CommandReload, "123"); err != nil { 376 t.Fatalf("ProcessSignal failed: %v", err) 377 } 378 379 if !called { 380 t.Fatal("Expected kill to be called") 381 } 382 } 383 384 func TestProcessSignalLameDuckMode(t *testing.T) { 385 killBefore := kill 386 called := false 387 kill = func(pid int, signal syscall.Signal) error { 388 called = true 389 if pid != 123 { 390 t.Fatalf("pid is incorrect.\nexpected: 123\ngot: %d", pid) 391 } 392 if signal != syscall.SIGUSR2 { 393 t.Fatalf("signal is incorrect.\nexpected: sigusr2\ngot: %v", signal) 394 } 395 return nil 396 } 397 defer func() { 398 kill = killBefore 399 }() 400 401 if err := ProcessSignal(commandLDMode, "123"); err != nil { 402 t.Fatalf("ProcessSignal failed: %v", err) 403 } 404 405 if !called { 406 t.Fatal("Expected kill to be called") 407 } 408 } 409 410 func TestProcessSignalTermDuringLameDuckMode(t *testing.T) { 411 opts := &Options{ 412 Host: "127.0.0.1", 413 Port: -1, 414 NoSigs: false, 415 NoLog: true, 416 LameDuckDuration: 2 * time.Second, 417 LameDuckGracePeriod: 1 * time.Second, 418 } 419 s := RunServer(opts) 420 defer s.Shutdown() 421 422 // Create single NATS Connection which will cause the server 423 // to delay the shutdown. 424 doneCh := make(chan struct{}) 425 nc, err := nats.Connect(fmt.Sprintf("nats://%s:%d", opts.Host, opts.Port), 426 nats.DisconnectHandler(func(*nats.Conn) { 427 close(doneCh) 428 }), 429 ) 430 if err != nil { 431 t.Fatalf("Error on connect: %v", err) 432 } 433 defer nc.Close() 434 435 // Trigger lame duck based shutdown. 436 go s.lameDuckMode() 437 438 // Wait for client to be disconnected. 439 select { 440 case <-doneCh: 441 break 442 case <-time.After(3 * time.Second): 443 t.Fatalf("Timed out waiting for client to disconnect") 444 } 445 446 // Termination signal should not cause server to shutdown 447 // while in lame duck mode already. 448 syscall.Kill(syscall.Getpid(), syscall.SIGTERM) 449 450 // Wait for server shutdown due to lame duck shutdown. 451 timeoutCh := make(chan error) 452 timer := time.AfterFunc(3*time.Second, func() { 453 timeoutCh <- errors.New("Timed out waiting for server shutdown") 454 }) 455 for range time.NewTicker(1 * time.Millisecond).C { 456 select { 457 case err := <-timeoutCh: 458 t.Fatal(err) 459 default: 460 } 461 462 if !s.isRunning() { 463 timer.Stop() 464 break 465 } 466 } 467 }