fix:修复panic恢复机制

This commit is contained in:
spiritlhl 2026-05-21 16:11:57 +00:00
parent 026f9784e4
commit ce8555f149
11 changed files with 94 additions and 21 deletions

View File

@ -5,6 +5,9 @@ on:
schedule:
- cron: '0 0 * * 0'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
fetch-ipv6-prefixes:
runs-on: ubuntu-latest

View File

@ -3,6 +3,9 @@ name: CI
on:
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
test:
strategy:
@ -30,7 +33,7 @@ jobs:
run: |
git config --global user.name 'github-actions'
git config --global user.email 'github-actions@github.com'
TAG="v0.0.8-$(date +'%Y%m%d%H%M%S')"
TAG="v0.0.9-$(date +'%Y%m%d%H%M%S')"
git tag $TAG
git push origin $TAG
echo "TAG=$TAG" >> $GITHUB_ENV

View File

@ -9,6 +9,9 @@ on:
# types: [published]
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
build:
name: Build and Test

View File

@ -117,7 +117,10 @@ func getSVGPath(ip string) (string, error) {
client := req.C().ImpersonateChrome()
url := fmt.Sprintf("https://bgp.tools/prefix/%s#connectivity", ip)
resp, err := executeWithRetry(client, url, defaultRetryConfig)
if err == nil {
if err == nil && resp != nil {
if resp.Body != nil {
defer resp.Body.Close()
}
body := resp.String()
re := regexp.MustCompile(`<img[^>]+id="pathimg"[^>]+src="([^"]+)"`)
matches := re.FindStringSubmatch(body)
@ -142,7 +145,8 @@ func downloadSVG(svgPath string) (string, error) {
uuid := uuid.NewString()
url := fmt.Sprintf("https://bgp.tools%s?%s&loggedin", svgPath, uuid)
resp, err := executeWithRetry(client, url, defaultRetryConfig)
if err == nil {
if err == nil && resp != nil && resp.Body != nil {
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err == nil {
return string(bodyBytes), nil

View File

@ -7,6 +7,14 @@ import (
"github.com/oneclickvirt/backtrace/model"
)
func safeTraceCall(fn func()) {
defer func() {
if r := recover(); r != nil {
}
}()
fn()
}
func BackTrace(enableIpv6 bool) string {
if model.CachedIcmpData == "" || model.ParsedIcmpTargets == nil || time.Since(model.CachedIcmpDataFetchTime) > time.Hour {
model.CachedIcmpData = getData(model.IcmpTargets)
@ -26,10 +34,16 @@ func BackTrace(enableIpv6 bool) string {
t = time.After(time.Second * 10)
)
for i := range model.Ipv4s {
go trace(c, i)
idx := i
go safeTraceCall(func() {
trace(c, idx)
})
}
for i := range model.Ipv6s {
go traceIPv6(c, i, ipv4Count)
idx := i
go safeTraceCall(func() {
traceIPv6(c, idx, ipv4Count)
})
}
loopIPv4v6:
for range s {
@ -62,7 +76,10 @@ func BackTrace(enableIpv6 bool) string {
t = time.After(time.Second * 10)
)
for i := range model.Ipv4s {
go trace(c, i)
idx := i
go safeTraceCall(func() {
trace(c, idx)
})
}
loopIPv4:
for range s {

View File

@ -233,7 +233,10 @@ func (t *Tracer) serveData(from net.IP, b []byte) error {
return err
}
if msg.Type == ipv4.ICMPTypeEchoReply {
echo := msg.Body.(*icmp.Echo)
echo, ok := msg.Body.(*icmp.Echo)
if !ok || echo == nil {
return errUnsupportedProtocol
}
return t.serveReply(from, &packet{from, uint16(echo.ID), 1, time.Now()})
}
b = getReplyData(msg)

View File

@ -58,6 +58,10 @@ func extractIpv4ASNsFromHops(hops []*Hop, enableLogger bool) []string {
// trace IPv4追踪函数
func trace(ch chan Result, i int) {
defer func() {
if r := recover(); r != nil {
}
}()
if model.EnableLoger {
InitLogger()
defer Logger.Sync()
@ -72,6 +76,10 @@ func trace(ch chan Result, i int) {
wg.Add(1)
go func(attemptNum int) {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
}
}()
if model.EnableLoger {
Logger.Info(fmt.Sprintf("第%d次尝试追踪 %s (%s)", attemptNum, model.Ipv4Names[i], model.Ipv4s[i]))
}

View File

@ -43,10 +43,21 @@ func (t *Tracer) serveIPv6(conn *ipv6.PacketConn) error {
}
return err
}
if model.EnableLoger {
Logger.Info(fmt.Sprintf("收到IPv6响应: 来源=%v, 跳数=%d", src, cm.HopLimit))
srcAddr, ok := src.(*net.IPAddr)
if !ok || srcAddr == nil {
continue
}
hopLimit := 0
if cm != nil {
hopLimit = cm.HopLimit
}
if model.EnableLoger {
Logger.Info(fmt.Sprintf("收到IPv6响应: 来源=%v, 跳数=%d", srcAddr, hopLimit))
}
fromIP := srcAddr.IP
if fromIP == nil {
continue
}
fromIP := src.(*net.IPAddr).IP
err = t.serveData(fromIP, buf[:n])
if err != nil && model.EnableLoger {
Logger.Warn("处理IPv6数据失败: " + err.Error())
@ -73,6 +84,10 @@ func extractIpv6ASNsFromHops(hops []*Hop, enableLogger bool) []string {
// traceIPv6 IPv6追踪函数
func traceIPv6(ch chan Result, i int, offset int) {
defer func() {
if r := recover(); r != nil {
}
}()
if model.EnableLoger {
InitLogger()
defer Logger.Sync()
@ -87,6 +102,10 @@ func traceIPv6(ch chan Result, i int, offset int) {
wg.Add(1)
go func(attemptNum int) {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
}
}()
if model.EnableLoger {
Logger.Info(fmt.Sprintf("第%d次尝试追踪 %s (%s)", attemptNum, model.Ipv6Names[i], model.Ipv6s[i]))
}

View File

@ -47,7 +47,7 @@ func checkCdn(testUrl string) string {
Logger.Info(fmt.Sprintf("Testing CDN: %s", url))
}
resp, err := client.R().Get(url)
if err == nil {
if err == nil && resp != nil && resp.Body != nil {
b, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err == nil && strings.Contains(string(b), "success") {
@ -92,7 +92,7 @@ func getData(endpoint string) string {
Logger.Info(fmt.Sprintf("Using CDN: %s", url))
}
resp, err := client.R().Get(url)
if err == nil {
if err == nil && resp != nil && resp.Body != nil {
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err == nil && !strings.Contains(string(b), "error") {
@ -112,7 +112,7 @@ func getData(endpoint string) string {
Logger.Info(fmt.Sprintf("Trying direct connection: %s", endpoint))
}
resp, err := client.R().Get(endpoint)
if err == nil {
if err == nil && resp != nil && resp.Body != nil {
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err == nil {

View File

@ -32,9 +32,23 @@ type ConcurrentResults struct {
// backtraceError error
}
func safeGo(wg *sync.WaitGroup, fn func()) {
go func() {
defer wg.Done()
defer func() {
if r := recover(); r != nil {
}
}()
fn()
}()
}
func main() {
go func() {
http.Get("https://hits.spiritlhl.net/backtrace.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
resp, err := http.Get("https://hits.spiritlhl.net/backtrace.svg?action=hit&title=Hits&title_bg=%23555555&count_bg=%230eecf8&edge_flat=false")
if err == nil && resp != nil && resp.Body != nil {
resp.Body.Close()
}
}()
fmt.Println(Green("Repo:"), Yellow("https://github.com/oneclickvirt/backtrace"))
var showVersion, showIpInfo, help, ipv6 bool
@ -62,6 +76,7 @@ func main() {
if err != nil {
fmt.Printf("get ip info err %v \n", err.Error())
} else {
defer rsp.Body.Close()
err = json.NewDecoder(rsp.Body).Decode(&info)
if err != nil {
fmt.Printf("json decode err %v \n", err.Error())
@ -106,8 +121,7 @@ func main() {
}
if targetIP != "" {
wg.Add(1)
go func() {
defer wg.Done()
safeGo(&wg, func() {
for i := 0; i < 2; i++ {
result, err := bgptools.GetPoPInfo(targetIP)
results.bgpError = err
@ -119,14 +133,13 @@ func main() {
time.Sleep(3 * time.Second)
}
}
}()
})
}
wg.Add(1)
go func() {
defer wg.Done()
safeGo(&wg, func() {
result := backtrace.BackTrace(useIPv6)
results.backtraceResult = result
}()
})
wg.Wait()
if results.bgpResult != "" {
fmt.Print(results.bgpResult)

View File

@ -2,7 +2,7 @@ package model
import "time"
const BackTraceVersion = "v0.0.8"
const BackTraceVersion = "v0.0.9"
var EnableLoger = false