dwarf: ensure Goroutine-safety in DWARFLines.Line function (#911)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
Takeshi Yoneda
2022-12-12 08:22:35 +09:00
committed by GitHub
parent e49995cdd3
commit 26bd24996e
2 changed files with 22 additions and 2 deletions

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"io"
"sort"
"sync"
)
// DWARFLines is used to retrieve source code line information from the DWARF data.
@@ -15,6 +16,7 @@ type DWARFLines struct {
// linesPerEntry maps dwarf.Offset for dwarf.Entry to the list of lines contained by the entry.
// The value is sorted in the increasing order by the address.
linesPerEntry map[dwarf.Offset][]line
mux sync.Mutex
}
type line struct {
@@ -37,6 +39,12 @@ func (d *DWARFLines) Line(instructionOffset uint64) string {
return ""
}
// DWARFLines is created per Wasm binary, so there's a possibility that multiple instances
// created from a same binary face runtime error at the same time, and that results in
// concurrent access to this function.
d.mux.Lock()
defer d.mux.Unlock()
r := d.d.Reader()
// Get the dwarf.Entry containing the instruction.

View File

@@ -3,6 +3,7 @@ package wasmdebug_test
import (
"fmt"
"math"
"sync"
"testing"
"github.com/tetratelabs/wazero/api"
@@ -44,8 +45,19 @@ func TestDWARFLines_Line_TinyGO(t *testing.T) {
for _, tc := range tests {
t.Run(tc.exp, func(t *testing.T) {
actual := mod.DWARFLines.Line(tc.offset)
require.Contains(t, actual, tc.exp)
// Ensures that DWARFLines.Line is goroutine-safe.
const concurrent = 100
var wg sync.WaitGroup
wg.Add(concurrent)
for i := 0; i < concurrent; i++ {
go func() {
defer wg.Done()
actual := mod.DWARFLines.Line(tc.offset)
require.Contains(t, actual, tc.exp)
}()
}
wg.Wait()
})
}
}