Browse Source

fix #1975

Provide a nondestructive stack trace dump option even when the http pprof
listener is disabled
tags/v2.11.0-rc1
Shivaram Lingamneni 1 year ago
parent
commit
d17faf6bcb
3 changed files with 28 additions and 5 deletions
  1. 21
    5
      irc/server.go
  2. 4
    0
      irc/utils/signals.go
  3. 3
    0
      irc/utils/signals_plan9.go

+ 21
- 5
irc/server.go View File

@@ -12,6 +12,7 @@ import (
12 12
 	_ "net/http/pprof"
13 13
 	"os"
14 14
 	"os/signal"
15
+	"runtime/pprof"
15 16
 	"strconv"
16 17
 	"strings"
17 18
 	"sync"
@@ -83,6 +84,7 @@ type Server struct {
83 84
 	rehashSignal      chan os.Signal
84 85
 	pprofServer       *http.Server
85 86
 	exitSignals       chan os.Signal
87
+	tracebackSignal   chan os.Signal
86 88
 	snomasks          SnoManager
87 89
 	store             *buntdb.DB
88 90
 	historyDB         mysql.MySQL
@@ -98,11 +100,12 @@ type Server struct {
98 100
 func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
99 101
 	// initialize data structures
100 102
 	server := &Server{
101
-		ctime:        time.Now().UTC(),
102
-		listeners:    make(map[string]IRCListener),
103
-		logger:       logger,
104
-		rehashSignal: make(chan os.Signal, 1),
105
-		exitSignals:  make(chan os.Signal, len(utils.ServerExitSignals)),
103
+		ctime:           time.Now().UTC(),
104
+		listeners:       make(map[string]IRCListener),
105
+		logger:          logger,
106
+		rehashSignal:    make(chan os.Signal, 1),
107
+		exitSignals:     make(chan os.Signal, len(utils.ServerExitSignals)),
108
+		tracebackSignal: make(chan os.Signal, len(utils.ServerTracebackSignals)),
106 109
 	}
107 110
 	server.defcon.Store(5)
108 111
 
@@ -120,6 +123,9 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
120 123
 	// Attempt to clean up when receiving these signals.
121 124
 	signal.Notify(server.exitSignals, utils.ServerExitSignals...)
122 125
 	signal.Notify(server.rehashSignal, syscall.SIGHUP)
126
+	if len(utils.ServerTracebackSignals) != 0 {
127
+		signal.Notify(server.tracebackSignal, utils.ServerTracebackSignals...)
128
+	}
123 129
 
124 130
 	time.AfterFunc(alwaysOnMaintenanceInterval, server.periodicAlwaysOnMaintenance)
125 131
 
@@ -158,6 +164,8 @@ func (server *Server) Run() {
158 164
 		case <-server.rehashSignal:
159 165
 			server.logger.Info("server", "Rehashing due to SIGHUP")
160 166
 			go server.rehash()
167
+		case <-server.tracebackSignal:
168
+			go server.dumpStacks()
161 169
 		}
162 170
 	}
163 171
 }
@@ -1128,3 +1136,11 @@ var (
1128 1136
     Edmund Huber,           edmund-huber
1129 1137
 `, "\n")
1130 1138
 )
1139
+
1140
+func (server *Server) dumpStacks() {
1141
+	if gprof := pprof.Lookup("goroutine"); gprof != nil {
1142
+		gprof.WriteTo(os.Stderr, 2)
1143
+	} else {
1144
+		server.logger.Error("internal", "unable to dump goroutine stacks")
1145
+	}
1146
+}

+ 4
- 0
irc/utils/signals.go View File

@@ -18,4 +18,8 @@ var (
18 18
 		syscall.SIGTERM,
19 19
 		syscall.SIGQUIT,
20 20
 	}
21
+
22
+	ServerTracebackSignals = []os.Signal{
23
+		syscall.SIGUSR1,
24
+	}
21 25
 )

+ 3
- 0
irc/utils/signals_plan9.go View File

@@ -18,4 +18,7 @@ var (
18 18
 		syscall.SIGINT,
19 19
 		syscall.SIGTERM,
20 20
 	}
21
+
22
+	// no SIGUSR1 on plan9
23
+	ServerTracebackSignals []os.Signal
21 24
 )

Loading…
Cancel
Save