How to circumvent SAP's maximum permitted uninterrupted runtime

Jimbo's picture

fast mountain goatTrimming the fat off of code in order to make programs run faster isn't at the top of the list of priorities for many ABAP developers because modern computers are so fast. However, when running complex programs, even the leanest code can run afoul of SAP's maximum permitted uninterrupted runtime limitation.

The workaround

One solution involves coaxing a BASIS resource into altering a system-wide parameter for one program. A better solution is breaking the program up so that it runs in brief interrupted sessions. An easy way to interrupt the program is by throwing a break-point into the program, but that doesn't work well with the coffee cup method.

A popop message, combined with a timer and a coffee cup, is a great way to interrupt a program often enough to avoid a runtime error. The SY-TIMLO contains a numeric time from the server that SAP is running on and subtracting a start time from it returns the total seconds that have elapsed.

This snippet is included in Jimbo's LSMW Toolbox, but its short code is easily copy-pasted from here into a LSMW User-Defined Routine or any report. It is embedded in a form to ensure that it can be called easily from an LSMW object using a one-line snippet of code included below.

It starts as always by defining the form and declaring variables. The statics hold their values between individual calls of the form so that no values to be maintained in the main LSMW object or passed in as parameters.

The first time the form is called, the lxStarted value is populated with the current time on the server (not on the client). This start time remains static each time the form is called and is reset to the current time each time the popup function is called.

When the appropriate number of seconds have pased, the POPUP_TO_CONFIRM function is called and the server starts the run-time clock at the beginning. The lxStarted variable is set to the current time on the server and the code that called this form continues to run without throwing a run-time exceeded error..

form CheckRuntime.
  statics:
           lxstarted like SY-UZEIT ,
           cRemaining(1) type c.
  data:  lvSeconds type i, lv_popup_ans type string,
         lvNow like SY-UZEIT.

  if cRemaining eq ''. cRemaining = 'X'. lxStarted = SY-UZEIT. endif.

  get time field lvNow.
  lvSeconds = lvNow - lxStarted.
  if lvSeconds gt 300.  " 5 minutes...
    call function 'POPUP_TO_CONFIRM'
      exporting
        titlebar = 'Time expired.'
        text_question = 'Keep going?'
        text_button_1 = 'OK'(011)
        default_button = '1'
        display_cancel_button = 'X'
        popup_type = 'ICON_MESSAGE_CRITICAL'
      importing
        answer = lv_popup_ans.
*    lxStarted = SY-UZEIT.  "Restart timer.
    get time field lxStarted.
  endif.
endform.

To call this form, put this snippet of code somewhere in the program. It requires no parameters as all the variables remain static each time the form is called.

perform CheckRuntime.  "Prevent timeouts.

The timeout of 300 seconds (five minutes) was set artificially low as many systems have short run-time exceeded values. Because the program will be run unattended, the number of appearances of the pop-up is inconsequential.

Caution: Be sure that this is not between a select and endselect; this will cause SAP to throw an error for "incorrectly interrupting a select", so dump some of it into an internal table and loop through it like this.

data: lKNA1 like KNA1, lCDHDR like CDHDR, lCDPOS like CDPOS,
      lKNVV like KNVV, lTABKEY like CDPOS-TABKEY.
data: it_KNVV type standard table of KNVV.

select * from KNVV into table it_KNVV where LOEVM eq 'X'
 order by KUNNR VKORG VTWEG SPART.
loop at it_KNVV into lKNVV.
  select * from CDHDR into lCDHDR
   where OBJECTID eq lKNVV-KUNNR and OBJECTCLAS eq 'DEBI'.
    if lCDHDR-UDATE gt '20200730'.
      concatenate sy-MANDT lKNVV-KUNNR lKNVV-VKORG lKNVV-VTWEG
       lKNVV-SPART into lTABKEY.
      select VALUE_NEW from CDPOS
       into corresponding fields of lCDPOS
       where OBJECTID eq lCDHDR-OBJECTID
         and OBJECTCLAS eq lCDHDR-OBJECTCLAS
         and CHANGENR eq lCDHDR-CHANGENR
         and TABKEY eq lTABKEY
         and FNAME eq 'LOEVM'.
        if lCDPOS-VALUE_NEW eq 'X'.
          write: / lKNVV-KUNNR, lKNVV-VKORG, lKNVV-VTWEG, lKNVV-SPART,
           lCDHDR-UDATE.
        endif.
      endselect.
    endif.
  endselect.
  perform CheckRuntime.  "Prevent timeouts.
endloop.

Finally, run the program and put something on the Enter key. This will click OK every time the popup is shown and allow the program to keep running.

Special thanks to Bharat Kalagara for the great response to this question. The value of the SY-TIMLO and SY-UZEIT values remain unchanged and the GET TIME FIELD code gets the actual time and not just the static time that the program started running.

Programming Language: 
ABAP