Uploaded image for project: 'CFEngine Community'
  1. CFEngine Community
  2. CFE-3072

Ability to time out any individual promises

    XMLWordPrintable

    Details

    • Type: Story
    • Status: Open
    • Priority: (None)
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: cf-agent
    • Labels:
      None

      Description

      Currently (as of 3.12.2) , not all promises can be timed out.

      Commonly the ifelapsed and expireafter attributes in action bodies are used to control the frequency of promises across agent executions.

      • ifelapsed: The number of minutes before next allowed assessment of a promise is set using ifelapsed. This overrides the global settings. Promises which take a long time to verify should usually be protected with a long value for this parameter.
      • expireafter: The Number of minutes a promise is allowed to run before the agent is terminated.
        • Note: Not to be confused with body contain exec_timeout in commands type promises, the original agent does not terminate the promise. When a subsequent agent notices that a promise actuation has persisted for longer than expireafter the subsequent agent will kill the agent that appears to be stuck on the long running promise.

      commands type promises can use contain bodies which have exec_timeout, but contain bodies are not usable for any other promise type.

      CFE-274 tracks a request to be able to set a custom timeout for readtcp(). One of the comments suggested a general timeout for all system functions, but I think that this would make sense as an action body attribute to timeout any long running promise.

      body action timeout
      {
          timeout => '1'; # Number of seconds after which the promsie should be timed out
      }
      

      Since action bodies can be used with any promise type, this is a natural place to introduce an attribute that applies to any promise type.

      This would be useful for preventing a hung command executed by execresult() or returnszero() as well as protecting against agent run slow-downs caused by readtcp(), or any other function.

      A promise that is timed out should work with repair_timeout in classes bodies, and be treated as a promise that is not kept or repaired.

      Investigating ability to timeout execresult()

      Do they ever time out?

      No, they don't. Indeed, they could get stuck, and that could result in an agent pile up.

      The expireafter attribute in action bodies is related to promise locking, which isn't supported by vars type promises.

      Trying to use execresult() with expireafter action body.
      bundle agent example_execresult
      {
        vars:
            "result"
              string => execresult( "/bin/sleep 120 && /bin/echo Hello",
                                    "useshell"),
              action => expireafter( 1 );
      
        reports: "$(result)"; 
      }
      body action expireafter( minutes )
      {
          expireafter => "$(minutes)";
      }
      bundle agent __main__
      {
        methods:
            "example_execresult";
      }
      

      Executing the example:

      Executing policy to show behaviour when vars are combined with expireafter attribute from an action body
      exec 2>&1
      /usr/bin/time cf-agent -KIf /tmp/execresult.cf 
      :
      

      The warning tells us that the expireafter action body attribute is not supported for vars type promises.

       warning: expireafter attribute specified in action body for vars promise 'result', but vars promises do not support promise locking
       warning: expireafter attribute specified in action body for vars promise 'result', but vars promises do not support promise locking
      R: Hello
      0.03user 0.02system 6:00.09elapsed 0%CPU (0avgtext+0avgdata 11728maxresident)k
      0inputs+360outputs (0major+3361minor)pagefaults 0swaps

      Commands promises can use contain bodies and the exec_timeout attribute to interrupt a promise execution, but contain bodies are not valid for vars type promises.

      Trying to use execresult() with exec_timeout in contain body.
      bundle agent example_execresult
      {
        vars:
            "result"
              string => execresult( "/bin/sleep 30 && /bin/echo Hello",
                                    "useshell"),
              contain => timeout( 10 );
      
        reports: "$(result)"; 
      }
      body action contain( seconds )
      {
          exec_timeout => "$(seconds)";
      }
      bundle agent __main__
      {
        methods:
            "example_execresult";
      }
      
      Executing policy to show behaviour when vars are combined with contain bodies
      exec 2>&1
      /usr/bin/time cf-agent -KIf /tmp/execresult_contain_exec_timeout.cf 
      :
      

      The execution output shows us that contain bodies are not valid for vars type promises in agent bundles.

      /tmp/execresult_contain_exec_timeout.cf:8:16: error: Unknown attribute 'contain' for promise type 'vars' in bundle with type 'agent'
              contain => timeout( 10 );
                     ^
      /tmp/execresult_contain_exec_timeout.cf:14:17: error: Unknown selection 'exec_timeout' for body type 'action'
          exec_timeout => "$(seconds)";
      

      How can I timeout commands executed with execresult() or returnszero()?

      You can use an external command like timeout

      Example timing out execresult() with timeout command
      bundle agent example_execresult
      {
        vars:
            "result"
              string => execresult( "/usr/bin/timeout 1 /bin/sleep 30 && echo hi",
                                    "useshell");
      
        reports: "$(result)"; 
      }
      
      bundle agent __main__
      {
        methods:
            "example_execresult";
      }
      

      Executing the example policy:

      Executing policy to show behaviour of policy timing out execresult()
      exec 2>&1
      /usr/bin/time cf-agent -KIf /tmp/execresult_timeout.cf 
      :
      

      We can see that result is left with an empty value since it never got to echo and that the entire agent execution lasted 3 seconds.

      R: 
      0.05user 0.02system 0:03.09elapsed 2%CPU (0avgtext+0avgdata 11772maxresident)k
      16inputs+360outputs (1major+3427minor)pagefaults 0swaps

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                a10042 Nick Anderson
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:

                  Summary Panel