// handleExecError handles panics during query execution and sets // the supplied error return value. func handleExecError(query *proto.Query, err *error, logStats *SQLQueryStats) { if x := recover(); x != nil { terr, ok := x.(*TabletError) if !ok { log.Errorf("Uncaught panic for %v:\n%v\n%s", query, x, tb.Stack(4)) *err = NewTabletError(FAIL, "%v: uncaught panic for %v", x, query) internalErrors.Add("Panic", 1) return } *err = terr terr.RecordStats() // suppress these errors in logs if terr.ErrorType == RETRY || terr.ErrorType == TX_POOL_FULL || terr.SqlError == mysql.DUP_ENTRY { return } if terr.ErrorType == FATAL { log.Errorf("%v: %v", terr, query) } else { log.Warningf("%v: %v", terr, query) } } if logStats != nil { logStats.Error = *err logStats.Send() } }
func handleError(err *error, logStats *SQLQueryStats) { if x := recover(); x != nil { terr, ok := x.(*TabletError) if !ok { log.Errorf("Uncaught panic:\n%v\n%s", x, tb.Stack(4)) *err = NewTabletError(FAIL, "%v: uncaught panic", x) internalErrors.Add("Panic", 1) return } *err = terr terr.RecordStats() if terr.ErrorType == RETRY { // Retry errors are too spammy return } if terr.ErrorType == TX_POOL_FULL { logTxPoolFull.Errorf("%v", terr) } else { log.Errorf("%v", terr) } } if logStats != nil { logStats.Error = *err logStats.Send() } }
func handlePanic(err *error) { if x := recover(); x != nil { log.Errorf("Uncaught panic:\n%v\n%s", x, tb.Stack(4)) *err = fmt.Errorf("uncaught panic: %v", x) internalErrors.Add("Panic", 1) } }
func handleInvalidationError(event *blproto.StreamEvent) { if x := recover(); x != nil { terr, ok := x.(*TabletError) if !ok { log.Errorf("Uncaught panic for %+v:\n%v\n%s", event, x, tb.Stack(4)) internalErrors.Add("Panic", 1) return } log.Errorf("%v: %+v", terr, event) internalErrors.Add("Invalidation", 1) } }
func logError() { if x := recover(); x != nil { terr, ok := x.(*TabletError) if !ok { log.Errorf("Uncaught panic:\n%v\n%s", x, tb.Stack(4)) internalErrors.Add("Panic", 1) return } if terr.ErrorType == TX_POOL_FULL { logTxPoolFull.Errorf("%v", terr) } else { log.Errorf("%v", terr) } } }
func (rci *RowcacheInvalidator) run(ctx *sync2.ServiceContext) error { for { evs := binlog.NewEventStreamer(rci.dbname, rci.mysqld, rci.Position(), rci.processEvent) // We wrap this code in a func so we can catch all panics. // If an error is returned, we log it, wait 1 second, and retry. // This loop can only be stopped by calling Close. err := func() (inner error) { defer func() { if x := recover(); x != nil { inner = fmt.Errorf("%v: uncaught panic:\n%s", x, tb.Stack(4)) } }() return evs.Stream(ctx) }() if err == nil { break } log.Errorf("binlog.ServeUpdateStream returned err '%v', retrying in 1 second.", err.Error()) internalErrors.Add("Invalidation", 1) time.Sleep(1 * time.Second) } log.Infof("Rowcache invalidator stopped") return nil }