| 570 | } |
| 571 | |
| 572 | void _killTask(const TaskID& taskId_, const Duration& gracePeriod) |
| 573 | { |
| 574 | CHECK_SOME(driver); |
| 575 | CHECK_SOME(frameworkInfo); |
| 576 | CHECK_SOME(taskId); |
| 577 | CHECK_EQ(taskId_, taskId.get()); |
| 578 | |
| 579 | if (!terminated) { |
| 580 | // Once the task has been transitioned to `killed`, |
| 581 | // there is no way back, even if the kill attempt |
| 582 | // failed. This also allows us to send TASK_KILLING |
| 583 | // only once, regardless of how many kill attempts |
| 584 | // have been made. |
| 585 | // |
| 586 | // Because we rely on `killed` to determine whether |
| 587 | // to send TASK_KILLED, we set `killed` only once the |
| 588 | // kill is issued. If we set it earlier we're more |
| 589 | // likely to send a TASK_KILLED without having ever |
| 590 | // signaled the container. Note that in general it's |
| 591 | // a race between signaling and the container |
| 592 | // terminating with a non-zero exit status. |
| 593 | if (!killed) { |
| 594 | killed = true; |
| 595 | |
| 596 | // Send TASK_KILLING if task is not killed by completion timeout and |
| 597 | // the framework can handle it. |
| 598 | if (!killedByTaskCompletionTimeout && |
| 599 | protobuf::frameworkHasCapability( |
| 600 | frameworkInfo.get(), |
| 601 | FrameworkInfo::Capability::TASK_KILLING_STATE)) { |
| 602 | // TODO(alexr): Use `protobuf::createTaskStatus()` |
| 603 | // instead of manually setting fields. |
| 604 | TaskStatus status; |
| 605 | status.mutable_task_id()->CopyFrom(taskId.get()); |
| 606 | status.set_state(TASK_KILLING); |
| 607 | |
| 608 | driver.get()->sendStatusUpdate(status); |
| 609 | } |
| 610 | |
| 611 | // Stop health checking the task. |
| 612 | if (checker.get() != nullptr) { |
| 613 | checker->pause(); |
| 614 | } |
| 615 | } |
| 616 | |
| 617 | // If a previous attempt to stop a Docker container is still in progress, |
| 618 | // we need to kill the hanging Docker CLI subprocess. Discarding this |
| 619 | // future triggers a callback in the Docker library that kills the |
| 620 | // subprocess. |
| 621 | if (stop.isPending()) { |
| 622 | LOG(WARNING) << "Previous docker stop has not terminated yet" |
| 623 | << " for container '" << containerName << "'"; |
| 624 | stop.discard(); |
| 625 | } |
| 626 | |
| 627 | // TODO(bmahler): Replace this with 'docker kill' so |
| 628 | // that we can adjust the grace period in the case of |
| 629 | // a `KillPolicy` override. |
nothing calls this directly
no test coverage detected