|
@@ -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
|
+}
|