Codebase list golang-github-vbauerster-mpb / 34431aa
refactoring: bar render panic recover Vladimir Bauer 3 years ago
2 changed file(s) with 38 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
1616
1717 // Bar represents a progress bar.
1818 type Bar struct {
19 index int // used by heap
20 priority int // used by heap
21 frameCh chan *renderFrame
22 operateState chan func(*bState)
23 done chan struct{}
24 container *Progress
25 bs *bState
26 cancel func()
27 recoveredPanic interface{}
19 index int // used by heap
20 priority int // used by heap
21 frameCh chan *renderFrame
22 operateState chan func(*bState)
23 done chan struct{}
24 container *Progress
25 bs *bState
26 cancel func()
2827 }
2928
3029 type extenderFunc func(rows []io.Reader, stat decor.Statistics) []io.Reader
4140 trimSpace bool
4241 completed bool
4342 aborted bool
43 recovered bool
4444 triggerComplete bool
4545 dropOnComplete bool
4646 noPop bool
6262 }
6363
6464 type renderFrame struct {
65 rows []io.Reader
66 shutdown int
65 rows []io.Reader
66 recovered bool
67 shutdown int
6768 }
6869
6970 func newBar(container *Progress, bs *bState) *Bar {
356357 }
357358
358359 func (b *Bar) render(tw int) {
359 select {
360 case b.operateState <- func(s *bState) {
360 var done bool
361 fn := func(s *bState) {
361362 var rows []io.Reader
362363 stat := newStatistics(tw, s)
363364 defer func() {
364365 // recovering if user defined decorator panics for example
365366 if p := recover(); p != nil {
366 if s.debugOut != nil {
367 go func() {
368 _, _ = fmt.Fprintln(b.container, p)
369 }()
370 if out := s.debugOut; out != nil {
367371 for _, fn := range []func() (int, error){
368372 func() (int, error) {
369 return fmt.Fprintln(s.debugOut, p)
373 return fmt.Fprintln(out, p)
370374 },
371375 func() (int, error) {
372 return s.debugOut.Write(debug.Stack())
376 return out.Write(debug.Stack())
373377 },
374378 } {
375379 if _, err := fn(); err != nil {
378382 }
379383 }
380384 s.aborted = !s.completed
381 s.extender = makePanicExtender(p)
382 b.recoveredPanic = p
383 }
384 if fn := s.extender; fn != nil {
385 rows = fn(rows, stat)
385 s.recovered = true
386 } else if s.extender != nil {
387 rows = s.extender(rows, stat)
386388 }
387389 frame := &renderFrame{
388 rows: rows,
389 }
390 if s.completed || s.aborted {
390 rows: rows,
391 recovered: s.recovered,
392 }
393 if !done && (s.completed || s.aborted) {
391394 b.cancel()
392395 frame.shutdown++
393396 }
394397 b.frameCh <- frame
395398 }()
396 if b.recoveredPanic == nil {
397 rows = append(rows, s.draw(stat))
398 }
399 }:
400 case <-b.done:
401 var rows []io.Reader
402 s, stat := b.bs, newStatistics(tw, b.bs)
403 if b.recoveredPanic == nil {
404 rows = append(rows, s.draw(stat))
405 }
406 if fn := s.extender; fn != nil {
407 rows = fn(rows, stat)
408 }
409 frame := &renderFrame{
410 rows: rows,
411 }
412 b.frameCh <- frame
399 rows = append(rows, s.draw(stat))
400 }
401 select {
402 case b.operateState <- fn:
403 case <-b.done:
404 done = true
405 fn(b.bs)
413406 }
414407 }
415408
605598 }
606599 return d
607600 }
608
609 func makePanicExtender(p interface{}) extenderFunc {
610 pstr := fmt.Sprint(p)
611 return func(rows []io.Reader, stat decor.Statistics) []io.Reader {
612 r := io.MultiReader(
613 strings.NewReader(runewidth.Truncate(pstr, stat.AvailableWidth, "…")),
614 bytes.NewReader([]byte("\n")),
615 )
616 return append(rows, r)
617 }
618 }
292292 var usedRows int
293293 b := heap.Pop(&s.bHeap).(*Bar)
294294 frame := <-b.frameCh
295 if frame.recovered {
296 s.heapUpdated = true
297 continue
298 }
295299 for i := len(frame.rows) - 1; i >= 0; i-- {
296300 if row := frame.rows[i]; len(rows) < height {
297301 rows = append(rows, row)