Codebase list golang-github-vbauerster-mpb / 529a634
don't recover in bar.render, handle error if any Vladimir Bauer 3 years ago
2 changed file(s) with 39 addition(s) and 57 deletion(s). Raw diff Collapse all Expand all
22 import (
33 "bytes"
44 "context"
5 "fmt"
65 "io"
7 "runtime/debug"
86 "strings"
97 "sync"
108 "time"
2624 cancel func()
2725 }
2826
29 type extenderFunc func(rows []io.Reader, stat decor.Statistics) []io.Reader
27 type extenderFunc func([]io.Reader, decor.Statistics) ([]io.Reader, error)
3028
3129 // bState is actual bar's state.
3230 type bState struct {
6260 }
6361
6462 type renderFrame struct {
65 rows []io.Reader
66 recovered bool
67 shutdown int
63 rows []io.Reader
64 shutdown int
65 err error
6866 }
6967
7068 func newBar(container *Progress, bs *bState) *Bar {
377375 fn := func(s *bState) {
378376 var rows []io.Reader
379377 stat := newStatistics(tw, s)
380 defer func() {
381 // recovering if user defined decorator panics for example
382 if p := recover(); p != nil {
383 go func() {
384 _, _ = fmt.Fprintln(b.container, p)
385 }()
386 if out := s.debugOut; out != nil {
387 for _, fn := range []func() (int, error){
388 func() (int, error) {
389 return fmt.Fprintln(out, p)
390 },
391 func() (int, error) {
392 return out.Write(debug.Stack())
393 },
394 } {
395 if _, err := fn(); err != nil {
396 panic(err)
397 }
398 }
399 }
400 s.aborted = !s.completed
401 s.recovered = true
402 }
403 frame := &renderFrame{
404 rows: rows,
405 recovered: s.recovered,
406 }
407 if !done && (s.completed || s.aborted) {
408 b.cancel()
409 frame.shutdown++
410 }
411 b.frameCh <- frame
412 }()
413 rows = append(rows, s.draw(stat))
378 r, err := s.draw(stat)
379 if err != nil {
380 b.frameCh <- &renderFrame{err: err}
381 return
382 }
383 rows = append(rows, r)
414384 if s.extender != nil {
415 rows = s.extender(rows, stat)
416 }
385 rows, err = s.extender(rows, stat)
386 if err != nil {
387 b.frameCh <- &renderFrame{err: err}
388 return
389 }
390 }
391 frame := &renderFrame{rows: rows}
392 if !done && (s.completed || s.aborted) {
393 frame.shutdown++
394 b.cancel()
395 }
396 b.frameCh <- frame
417397 }
418398 select {
419399 case b.operateState <- fn:
465445 }
466446 }
467447
468 func (s *bState) draw(stat decor.Statistics) io.Reader {
448 func (s *bState) draw(stat decor.Statistics) (io.Reader, error) {
469449 r, err := s.drawImpl(stat)
470450 if err != nil {
471451 for _, b := range s.buffers {
472452 b.Reset()
473453 }
474 panic(err)
475 }
476 return io.MultiReader(r, strings.NewReader("\n"))
454 return nil, err
455 }
456 return io.MultiReader(r, strings.NewReader("\n")), nil
477457 }
478458
479459 func (s *bState) drawImpl(stat decor.Statistics) (r io.Reader, err error) {
128128
129129 func makeExtenderFunc(filler BarFiller, rev bool) extenderFunc {
130130 buf := new(bytes.Buffer)
131 base := func(rows []io.Reader, stat decor.Statistics) []io.Reader {
131 base := func(rows []io.Reader, stat decor.Statistics) ([]io.Reader, error) {
132132 err := filler.Fill(buf, stat)
133133 if err != nil {
134134 buf.Reset()
135 panic(err)
135 return rows, err
136136 }
137137 for {
138138 b, err := buf.ReadBytes('\n')
142142 rows = append(rows, bytes.NewReader(b))
143143 }
144144 buf.Reset()
145 return rows
145 return rows, err
146146 }
147147
148148 if !rev {
149149 return base
150 } else {
151 return func(rows []io.Reader, stat decor.Statistics) []io.Reader {
152 rows = base(rows, stat)
153 for left, right := 0, len(rows)-1; left < right; left, right = left+1, right-1 {
154 rows[left], rows[right] = rows[right], rows[left]
155 }
156 return rows
157 }
150 }
151 return func(rows []io.Reader, stat decor.Statistics) ([]io.Reader, error) {
152 rows, err := base(rows, stat)
153 if err != nil {
154 return rows, err
155 }
156 for left, right := 0, len(rows)-1; left < right; left, right = left+1, right-1 {
157 rows[left], rows[right] = rows[right], rows[left]
158 }
159 return rows, err
158160 }
159161 }
160162