mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-12 10:47:05 +02:00
Move error handling code into its own library
This commit is contained in:
@@ -68,80 +68,6 @@ func Filter[T any](s []T, f func(x T) bool) []T {
|
||||
return ans
|
||||
}
|
||||
|
||||
func Format_stacktrace_on_panic(r any) (text string, err error) {
|
||||
pcs := make([]uintptr, 512)
|
||||
n := runtime.Callers(3, pcs)
|
||||
lines := []string{}
|
||||
frames := runtime.CallersFrames(pcs[:n])
|
||||
rt := fmt.Sprint(r)
|
||||
if strings.HasPrefix(rt, "Panicked with error:") {
|
||||
err = fmt.Errorf("%s", rt)
|
||||
lines = append(lines, "Panic caused by previous panic (probably in a gouroutine). Previous panic:\r\n")
|
||||
lines = append(lines, rt)
|
||||
lines = append(lines, "\r\n\r\nStacktrace of current panic (most recent call first):\r\n")
|
||||
} else {
|
||||
err = fmt.Errorf("Panicked: %s", r)
|
||||
lines = append(lines, fmt.Sprintf("\r\nPanicked with error: %s\r\nStacktrace (most recent call first):\r\n", r))
|
||||
}
|
||||
found_first_frame := false
|
||||
for frame, more := frames.Next(); more; frame, more = frames.Next() {
|
||||
if !found_first_frame {
|
||||
if strings.HasPrefix(frame.Function, "runtime.") {
|
||||
continue
|
||||
}
|
||||
found_first_frame = true
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf("%s\r\n\t%s:%d\r\n", frame.Function, frame.File, frame.Line))
|
||||
}
|
||||
text = strings.Join(lines, "")
|
||||
return strings.TrimSpace(text), err
|
||||
}
|
||||
|
||||
// Run the specified function in parallel over chunks from the specified range.
|
||||
// If the function panics, it is turned into a regular error.
|
||||
func Run_in_parallel_over_range(num_procs int, f func(int, int) error, start, limit int) (err error) {
|
||||
num_items := limit - start
|
||||
if num_procs <= 0 {
|
||||
num_procs = runtime.NumCPU()
|
||||
}
|
||||
num_procs = max(1, min(num_procs, num_items))
|
||||
if num_procs < 2 {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
stacktrace, e := Format_stacktrace_on_panic(r)
|
||||
err = fmt.Errorf("%s\n\n%w", stacktrace, e)
|
||||
}
|
||||
}()
|
||||
return f(start, limit)
|
||||
}
|
||||
chunk_sz := max(1, num_items/num_procs)
|
||||
var wg sync.WaitGroup
|
||||
echan := make(chan error, num_procs)
|
||||
for start < limit {
|
||||
end := min(start+chunk_sz, limit)
|
||||
wg.Add(1)
|
||||
go func(start, end int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
stacktrace, e := Format_stacktrace_on_panic(r)
|
||||
echan <- fmt.Errorf("%s\n\n%w", stacktrace, e)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
if err := f(start, end); err != nil {
|
||||
echan <- err
|
||||
}
|
||||
}(start, end)
|
||||
start = end
|
||||
}
|
||||
wg.Wait()
|
||||
close(echan)
|
||||
for qerr := range echan {
|
||||
return qerr
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
func Map[T any, O any](f func(x T) O, s []T) []O {
|
||||
ans := make([]O, 0, len(s))
|
||||
for _, x := range s {
|
||||
|
||||
Reference in New Issue
Block a user