github.com/nats-io/nats-server/v2@v2.11.0-preview.2/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  	"github.com/nats-io/nats-server/v2/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  }