Interrupt a long-running action callback in Java

I have various action callbacks registered in Java. For example:

@ActionCallback(callPoint=“my-action”, callType=ActionCBType.ACTION)
public ConfXMLParam[] action(DpActionTrans trans, ConfTag name,
ConfObject[] kp, ConfXMLParam[] params) throws DpCallbackException {
etc.
}

I’d like to be able to interrupt such actions from the ConfD CLI. The User Guide mentions an interrupt() handler:

interrupt()

This callback is optional. Unlike the other transaction callbacks, it does not imply a change of the transaction state, it is instead a notification that the user running the transaction requested that it should be interrupted (e.g. Ctrl-C in the CLI). Also unlike the other transaction callbacks, the callback request is sent asynchronously on the control socket. Registering this callback may be useful for a configuration data provider that has some (transaction or data) callbacks which require extensive processing - the callback could then determine whether one of these callbacks is being processed, and if feasible return an error from that callback instead of completing the processing. In that case, confd_trans_seterr_extended() with code CONFD_ERRCODE_INTERRUPT should be used.

That is given in the context of the C API. However, I have not been able to find anything corresponding to this in the JavaDoc for the Java API. In the JavaDoc, I do see an ActionCBType.ABORT, but I tried this and the callback never gets called when I CTRL-C in the CLI. I am thinking that this is for aborting a transaction, not the CLI interrupt handler.

The User Guide also mentions using tailf:interrupt in YANG. However, this is in the “Action as an executable” section of the guide. In my case, the actions are not executables. I am not using tailf:exec.

Can you offer any advice on how to enable CTRL-C interrupt of an action callback written in Java?

Thank you.

The ConfD example intro/java/7-action shows exactly this - the abort handler is registered using ActionCBType.ABORT call type and as far as I can tell, it works just fine. Are you saying the same does not work in your case?

Yes, in my code, the callback using ActionCBType.ABORT does not work. The handler is never entered during execution. Either it is not getting registered properly, or my CLI is not interpreting the CTRL-C properly.

I believe it is registered, as I am using registerAnnotatedCallbacks() on the entire class, and the ACTION callback is working.

When I type CTRL-C in the CLI numerous times to try and interrupt the output of my action handler, the CTRL-C is not getting ignored. It is getting processed, but only after the action completes. The CTRL C then kicks me out of the config mode of the CLI, back to enable mode. So I know CTRL-C is being passed to the CLI properly, but just not in time to interrupt the action.

Sorry for the late response. The behavior you describe corresponds pretty much to how it would behave if the ABORT callback was not registered properly. You can check if the registration was as expected by looking at the output of confd --status; in the Java action example where the action point is called reboot-point you can get this:

$ confd --status | grep reboot-point
  id=reboot-point daemonId=6 daemonName=action_daemon callbacks=action,abort,init
$

Note abort among callbacks.

Thank you for this suggestion. I tried using confd --status, and it doesn’t show the abort callback, but it doesn’t show the init or action callbacks either. I know that the action callback is functional because it works. Here is what confd --status shows under “actionpoints” for this particular actionpoint (in our code, it’s “syslog-action”):

id=syslog-action daemonId=3 daemonName=Cli Server callbacks=get_next,get_elem,exists

In fact, our other actionpoints show these same callbacks, for the most part. None of them show “action” after callbacks, even the ones that are known to have actions registered and working.

Thats really weird, get_elem etc. are data provider callbacks, not action callbacks. Can you double-check how you declare and register it? Btw., there’s another way how to check the runtime status - provided your system opens the NETCONF interface and ConfD has tailf-confd-monitoring on its loadpath, you can also do something like

$ netconf-console --get -x /confd-state/internal/callpoints/actionpoint
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <data>
    <confd-state xmlns="http://tail-f.com/yang/confd-monitoring">
      <internal>
        <callpoints>
          <actionpoint>
            <id>reboot-point</id>
            <daemon>
              <id>2</id>
              <name>action_daemon</name>
              <callbacks>action</callbacks>
              <callbacks>abort</callbacks>
              <callbacks>init</callbacks>
            </daemon>
          </actionpoint>
        </callpoints>
      </internal>
    </confd-state>
  </data>
</rpc-reply>
$
1 Like

By “how you declare” I mean how it looks like in your YANG module; there should be something like

   tailf:action action {
     tailf:actionpoint syslog-action;
     input { ... }
     output { ... }
   }

Or any variant of this, through annotation, or using YANG-1.1 construct action, etc.

1 Like

Great! thanks for sharing.