Log an unexpected error that was encountered.

The stack trace did not make it evidant which request had caused this
issue, so add extra logging for the request that caused it.  Sanitize
this request if it may contain any secrets.

Additionally, in this situation, begin shutting down the wallet rather
than simply dropping the response.  This will help to catch the issue
since it's easier to notice all requests failing, rather than just one
that was dropped.  If shutdown takes an unreasonably long time, panic.
This commit is contained in:
Josh Rickmar 2014-08-14 14:23:47 -05:00
parent 7b90b48bc6
commit 97c9d986d4

View file

@ -658,6 +658,27 @@ type rawRequest struct {
Params []json.RawMessage `json:"params"`
}
// String returns a sanitized string for the request which may be safely
// logged. It is intended to strip private keys, passphrases, and any other
// secrets from request parameters before they may be saved to a log file.
//
// This intentionally implements the fmt.Stringer interface to prevent
// accidental leaking of secrets.
func (r *rawRequest) String() string {
// These are considered unsafe to log, so sanitize parameters.
switch r.Method {
case "encryptwallet", "importprivkey", "importwallet",
"signrawtransaction", "walletpassphrase",
"walletpassphrasechange":
return fmt.Sprintf(`{"id":%v,"method":"%s","params":SANITIZED %d parameters}`,
r.ID, r.Method, len(r.Params))
}
return fmt.Sprintf(`{"id":%v,"method":"%s","params":%v}`, r.ID,
r.Method, r.Params)
}
// idPointer returns a pointer to the passed ID, or nil if the interface is nil.
// Interface pointers are usually a red flag of doing something incorrectly,
// but this is only implemented here to work around an oddity with btcjson,
@ -796,7 +817,22 @@ out:
resp := f(request, raw)
mresp, err := json.Marshal(resp)
if err != nil {
panic(err)
// Completely unexpected error, but have seen
// it happen regardless. Log the sanitized
// request and begin clean shutdown, panicing
// if shutdown takes too long.
log.Criticalf("Unexpected error marshaling "+
"response for request '%s': %v",
raw, err)
wsc.wg.Done()
s.Stop()
go func() {
time.Sleep(30 * time.Second)
panic("shutdown took too long")
}()
return
}
_ = wsc.send(mresp)