| 555 | } |
| 556 | |
| 557 | func (s *sequenceState) expire(e *event.Event) bool { |
| 558 | if !e.IsTerminateProcess() { |
| 559 | return false |
| 560 | } |
| 561 | canExpire := func(lhs, rhs *event.Event, isFinalSlot bool) bool { |
| 562 | // if the TerminateProcess event arrives for the |
| 563 | // process spawned by CreateProcess, and it pertains |
| 564 | // to the final sequence slot, it is safe to expire |
| 565 | // the whole sequence |
| 566 | pid := rhs.Params.MustGetPid() |
| 567 | if lhs.Type == event.CreateProcess && isFinalSlot { |
| 568 | return lhs.Params.MustGetPid() == pid |
| 569 | } |
| 570 | if lhs.Type == event.CreateThread { |
| 571 | // if the pids differ, the thread |
| 572 | // is created in a remote process. |
| 573 | // Sequence can be expired only if |
| 574 | // the remote process terminates |
| 575 | if lhs.PID != lhs.Params.MustGetPid() { |
| 576 | return lhs.Params.MustGetPid() == pid |
| 577 | } |
| 578 | } |
| 579 | return lhs.PID == pid |
| 580 | } |
| 581 | s.mu.Lock() |
| 582 | defer s.mu.Unlock() |
| 583 | s.smu.RLock() |
| 584 | defer s.smu.RUnlock() |
| 585 | |
| 586 | for idx := range s.exprs { |
| 587 | for i := len(s.partials[idx]) - 1; i >= 0; i-- { |
| 588 | if len(s.partials[idx]) > 0 && !canExpire(s.partials[idx][i], e, idx == len(s.exprs)-1) { |
| 589 | continue |
| 590 | } |
| 591 | log.Debugf("removing event originated from %s (%d) "+ |
| 592 | "in partials pertaining to sequence [%s] and slot [%d]", |
| 593 | e.Params.MustGetString(params.ProcessName), |
| 594 | e.Params.MustGetPid(), |
| 595 | s.name, |
| 596 | idx) |
| 597 | // remove partial event from the corresponding slot |
| 598 | s.partials[idx] = append( |
| 599 | s.partials[idx][:i], |
| 600 | s.partials[idx][i+1:]...) |
| 601 | partialsPerSequence.Add(s.name, -1) |
| 602 | |
| 603 | if len(s.partials[idx]) == 0 { |
| 604 | partialExpirations.Add(s.name, 1) |
| 605 | log.Debugf("%q sequence expired. All partials retracted", s.name) |
| 606 | s.inExpired.Store(true) |
| 607 | err := s.expireTransition() |
| 608 | if err != nil { |
| 609 | s.inExpired.Store(false) |
| 610 | log.Warnf("expire transition failed: %v", err) |
| 611 | } |
| 612 | // transitions from expired state to initial state |
| 613 | err = s.fsm.Fire(resetTransition) |
| 614 | if err != nil { |