Skip to content

Commit

Permalink
Fix heartbeat races on event updates (elastic#6950) (elastic#7008)
Browse files Browse the repository at this point in the history
Heartbeat has a many components, each adding fields to an existing
event. As events are created per 'TaskRun', this is normally fine. But
in case the TaskRunner branches of into multiple Sub-tasks, we will see
races on shared event structures. This is the case with multiple ports
in the http/tcp configuration or the IPAll setting (ping all known IPs
of a given domain).

Namespaces in an event can be potentially populated via globally shared
structures. This can also lead to unwanted updates or races.

This fix clones the event structure before continuing event updates, so
to remove the chance of races.

(cherry picked from commit bc225fb)
  • Loading branch information
Steffen Siering authored and ruflin committed May 4, 2018
1 parent 1f41c12 commit b3d5ad4
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ https://github.com/elastic/beats/compare/v6.2.4...6.2[Check the HEAD diff]
*Filebeat*

*Heartbeat*
- Fix race due to updates of shared a map, that was not supposed to be shared between multiple go-routines. {issue}6616[6616]

*Metricbeat*

Expand Down
11 changes: 8 additions & 3 deletions heartbeat/monitors/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ func annotated(
}

if fields != nil {
fields = fields.Clone()

status := look.Status(err)
fields.DeepUpdate(common.MapStr{
"monitor": common.MapStr{
Expand All @@ -130,7 +132,7 @@ func annotated(
},
})
if user := settings.Fields; user != nil {
fields.DeepUpdate(user)
fields.DeepUpdate(user.Clone())
}

event.Timestamp = start
Expand Down Expand Up @@ -370,10 +372,13 @@ func resolveErr(host string, err error) (common.MapStr, []TaskRunner, error) {
func WithFields(fields common.MapStr, r TaskRunner) TaskRunner {
return MakeCont(func() (common.MapStr, []TaskRunner, error) {
event, cont, err := r.Run()
if event == nil {
if event != nil {
event = event.Clone()
event.DeepUpdate(fields)
} else if err != nil {
event = common.MapStr{}
event.DeepUpdate(fields)
}
event.DeepUpdate(fields)

for i := range cont {
cont[i] = WithFields(fields, cont[i])
Expand Down

0 comments on commit b3d5ad4

Please sign in to comment.