#go
#Вперед
Вопрос:
Я получаю сообщение о странной скачке данных при использовании xml.Marshal
в структуре. Я на 99% уверен, что я не отправляю ту же переменную или что-то в этом роде — вместо этого я получаю периодические ошибки, в которых функция marshal считает, что это вызывает скачок данных.
Вот код (немного упрощенный, но все функциональные элементы присутствуют):
// this is run prior to any calls being sent to the below functions
func Setup() (descriptor *serviceDescriptor) {
descriptor = new(serviceDescriptor)
wpChan := make(chan *Call)
for i := 1; i < 100; i {
go serviceWorker(wpChan)
}
descriptor.wpChan = wpChan
return
}
// called externally to initiate a call
func (s *serviceDescriptor) Add(c *Call) {
go s.makeCall(c)
}
// sends a call to the worker pool set up in the Setup() function
func (s *serviceDescriptor) makeCall(c *Call) {
cw := new(callwrapper)
cw.internal = new(etFullCall)
cw.internal.Calldata = c
/// this is a channel that the next function listens to
s.wpChan <- ct
// the result is sent back on a channel and processed here
}
// this is a function
func worker(wpChan chan *callwrapper) {
for cw := range wpChan {
v := new(Result)
// this is where the data race occurs.
byt, err := xml.Marshal(cw.internal)
// do stuff with the result down here
}
}
Вот ошибка:
WARNING: DATA RACE
Write by goroutine 115:
runtime.copy()
/usr/lib/go/src/pkg/runtime/slice.c:120 0x0
encoding/xml.(*parentStack).push()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:901 0x2bd
encoding/xml.(*printer).marshalStruct()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:819 0x58c
encoding/xml.(*printer).marshalValue()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:524 0x12a8
encoding/xml.(*Encoder).Encode()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:153 0x83
encoding/xml.Marshal()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:72 0x9d
exacttarget.serviceWorker()
/service.go:94 0x20e
Previous write by goroutine 114:
runtime.copy()
/usr/lib/go/src/pkg/runtime/slice.c:120 0x0
encoding/xml.(*parentStack).push()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:901 0x2bd
encoding/xml.(*printer).marshalStruct()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:819 0x58c
encoding/xml.(*printer).marshalValue()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:524 0x12a8
encoding/xml.(*Encoder).Encode()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:153 0x83
encoding/xml.Marshal()
/usr/lib/go/src/pkg/encoding/xml/marshal.go:72 0x9d
exacttarget.serviceWorker()
/service.go:94 0x20e
Goroutine 115 (running) created at:
service.Setup()
/service.go:39 0x112
/src.processSingleUser()
/main_test.go:405 0xdf
/src.testAddLists()
/main_test.go:306 0x1f2
Goroutine 114 (running) created at:
service.Setup()
/service.go:39 0x112
/src.processSingleUser()
/main_test.go:405 0xdf
src.testAddLists()
/main_test.go:306 0x1f2
Комментарии:
1. Давайте поиграем в «Найди php-программиста»! что-то в пропущенном коде должно быть причиной гонки.
2. @OneOfOne это, конечно, возможно. Мы приложили усилия, чтобы убедиться, что каждая операция является идемпотентной. Каждая подпрограмма создает новую структуру вызова, и с ними не выполняется никаких дальнейших манипуляций. Пожалуйста, дайте мне знать, если вам понадобится дополнительная информация, чтобы помочь в отладке этого.
3. читая эту трассировку стека и код, стоящий за ней, я на 90% уверен, что это ложноположительный результат. И если бы это был истинный положительный результат, вы не смогли бы это исправить без изменения
slice.c
или переопределения кодировщика xml.4. можете ли вы попытаться воспроизвести небольшой тестовый пример?
5. Что касается фактической гонки, она не похожа на гонку из
encoding/xml
. Более вероятно, что вы передаете один указатель на несколькоxml.Marshal
‘s. Без полного кода мало что может помочь.