Reputation: 1820
Calling the function ME_INFORECORD_MAINTAIN_MULTI
multiple times via RFC fails with the short dump "Maximum number of GUI sessions reached", but other functions don't seem to be subjected to the sessions limit when called in the same way.
The number of parallel calls to this function that I'm allowed to make depends on the number of GUI sessions (SAP GUI windows) that I have currently opened.
For example, the following code fails after 5 calls (I've added >>>
at the beginning of the line where the dump occurs):
FORM CALL_BAPI_INFORECORD.
lv_taskname = |PIR-{ lv_sentjobs WIDTH = 3 ALIGN = RIGHT PAD = '0' }|.
DATA: lv_retry TYPE ABAP_BOOL.
lv_retry = ABAP_TRUE.
WHILE lv_retry = ABAP_TRUE.
lv_retry = ABAP_FALSE.
CALL FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
STARTING NEW TASK lv_taskname
DESTINATION IN GROUP DEFAULT
PERFORMING RETURN_BAPI_INFORECORD ON END OF TASK
[...]
EXCEPTIONS
system_failure = 1 MESSAGE lv_exceptionmsg
communication_failure = 2 MESSAGE lv_exceptionmsg
resource_failure = 3
CASE sy-subrc.
WHEN 0.
lv_sentjobs = lv_sentjobs + 1.
WHEN 1 OR 2.
MESSAGE lv_exceptionmsg TYPE 'I'.
WRITE: / lv_taskname, ':', lv_exceptionmsg.
WHEN 3.
WAIT FOR ASYNCHRONOUS TASKS UNTIL lv_recvjobs = lv_sentjobs UP TO 300 SECONDS.
lv_retry = ABAP_TRUE.
WHEN OTHERS.
MESSAGE 'Unkown error.' TYPE 'I'.
ENDCASE.
ENDWHILE.
ENDFORM.
FORM RETURN_BAPI_INFORECORD USING TASKNAME.
DATA INFO LIKE RFCSI.
>>> RECEIVE RESULTS FROM FUNCTION 'ME_INFORECORD_MAINTAIN_MULTI'
IMPORTING
RFCSI_EXPORT = INFO
RETURN = GT_ME_INFORECORD_RETURN.
ENDFORM.
... but the following code runs fine with 10 parallel calls:
FORM CALL_BAPI_MATERIAL.
lv_taskname = |MAT-{ lv_sentjobs WIDTH = 3 ALIGN = RIGHT PAD = '0' }|.
DATA: lv_retry TYPE ABAP_BOOL.
lv_retry = ABAP_TRUE.
WHILE lv_retry = ABAP_TRUE.
lv_retry = ABAP_FALSE.
CALL FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
STARTING NEW TASK lv_taskname
DESTINATION IN GROUP DEFAULT
PERFORMING RETURN_BAPI_MATERIAL ON END OF TASK
[...]
EXCEPTIONS
system_failure = 1 MESSAGE lv_exceptionmsg
communication_failure = 2 MESSAGE lv_exceptionmsg
resource_failure = 3.
CASE sy-subrc.
WHEN 0.
lv_sentjobs = lv_sentjobs + 1.
WHEN 1 OR 2.
MESSAGE lv_exceptionmsg TYPE 'I'.
WRITE: / lv_taskname, ':', lv_exceptionmsg.
WHEN 3.
WAIT FOR ASYNCHRONOUS TASKS UNTIL lv_recvjobs = lv_sentjobs UP TO 300 SECONDS.
lv_retry = ABAP_TRUE.
WHEN OTHERS.
MESSAGE 'Unknown error.' TYPE 'I'.
ENDCASE.
ENDWHILE.
ENDFORM.
FORM RETURN_BAPI_MATERIAL USING TASKNAME.
DATA INFO LIKE RFCSI.
RECEIVE RESULTS FROM FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
IMPORTING
RFCSI_EXPORT = INFO
RETURNMESSAGES = GT_BAPI_SAVEREPLICA_RETURN.
ENDFORM.
This is the stack when the dump occurs.
Why is function ME_INFORECORD_MAINTAIN_MULTI subject to a limit of GUI sessions and how to bypass it ?
Upvotes: 2
Views: 1639
Reputation: 1
There are some cases where function modules raises GUI sessions ("ABAP sessions") internally. It's caused by internal processing that calls dialog modules.
"When dynpros are called in aRFC processing, additional ABAP sessions are opened in the RFC client (see also RFC Dialog Interactions. The maximum number of ABAP sessions cannot be exceeded and if there are more, an error message is displayed. The maximum number of sessions is defined in the profile parameter rdisp/max_alt_modes and cannot be greater than 16."
https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapcall_function_starting.htm
Upvotes: 0
Reputation: 11348
Are you sure you got error
"Maximum number of GUI sessions reached"
due to the function call?
CALL FUNCTION 'BAPI_MATERIAL_SAVEREPLICA'
STARTING NEW TASK lv_taskname
DESTINATION IN GROUP DEFAULT
PERFORMING RETURN_BAPI_MATERIAL ON END OF TASK
Did you include the exceptions on the call function statement?
exceptions resource_failure = 1
others = 2.
When there are no more free resources on the Group you will get a 'resource_failure' exception. I would expect a resource failure error based on your description.
Check the settings in Rz12 of for the server group you are using.
The ability to "start new task" (via rfc) checks these parameter settings.
So if the server was "busy" then the call fails.
Here is a basic shell program you can use to test parallel code behavior.
REPORT ZPARA.
data t type i.
parameters:
cnt type i default 10000000,
packets type i default 10,
para as checkbox default 'X',
waittime type i default 1,
rfcgroup like rzllitab-classname .
data total type f.
data splits type i.
data mod type i.
data packetsize type i.
data: first type i.
data: last type i.
data: this_last type i.
data: this_split type i.
data: ret_splits type i.
data: act_splits type i.
data: taskname type num8 value 0.
data: begin of task occurs 0,
taskname type num8,
uzeit like sy-uzeit,
wpinfo TYPE WPINFO,
end of task.
data max_pbt_wps type i.
data free_pbt_wps type i.
start-of-selection.
PERFORM classic_version.
form classic_version.
**** TO USE THIS CODE,
* create a parallel(rfc) server group in RZ12.
* create the function decribed below
**************************************************
* set run time res low, so measurement in milli not microsecs.
* we are measure BIG runs
refresh task.
set run time clock resolution low.
get run time field t.
total = 0.
check cnt > 0.
if packets = 0.
packets = 5.
endif.
* splits calculated based on packet size
splits = packets.
PACKETSIZE = cnt div PACKETS.
* is parallel mode selected
if para = 'X'.
* parallel processing MUST be initialized first.
call function 'SPBT_INITIALIZE'
exporting
group_name = rfcgroup
importing
max_pbt_wps = max_pbt_wps
free_pbt_wps = free_pbt_wps
exceptions
invalid_group_name = 1
internal_error = 2
pbt_env_already_initialized = 3
currently_no_resources_avail = 4
no_pbt_resources_found = 5
cant_init_different_pbt_groups = 6
others = 7
.
if sy-subrc <> 0.
* if our group failed or the available processes was 0,
* we would exit cleanly here.
* for the demo, just bomb out.
endif.
last = 0.
ret_splits = 0.
act_splits = 0.
* so for each split
do splits times.
* make a jobname
taskname = taskname + 1.
* work out which chunk we are processing
* ie were are we up to ??
first = last + 1.
this_last = first + packetsize - 1.
* for info purposes record which split
this_split = sy-index.
* just in case we have the last split,
* calculated adjust target end,
if this_last > cnt.
this_last = cnt.
endif.
* try a dispatch this split.
* this is where more logic is needed.
* here we set a max of a hundred tries to dispatch
* something. IN VERY LARGE jobs,
* a commit work and a more intelligent wait
* might be appropriate.
* we at least wait, 1 then 2 then 3... secs etc
* until we get a look in.
do 100 times.
* inside a parallel ( new ) task
* do a chunk of work.
* NO importing parameters here. The result is returned
* in the receiving function.
* SPECIAL, extra, exceptions are available to control
* success or otherwise of the dispatch.
write: / 'Split ', this_split, 'dispatch at', sy-uzeit.
call function 'Z_CHUNK' starting new task taskname
destination in group rfcgroup
performing finished on end of task
exporting
from_int = first
to_int = this_last
exceptions
resource_failure = 1
others = 2.
if sy-subrc = 0.
* dispatch ok, record the fact and march on...
act_splits = act_splits + 1.
last = first + PACKETSIZE - 1.
exit. " the retry until dispatched loop.
else.
write: 'No resource free'.
write: / 'Split ', this_split, 'Waits ', waittime, 'secs at',
sy-uzeit.
* wait x seconds, each attempt waits successlively longer
wait up to waittime seconds.
endif.
enddo.
* Actual failure to dispatch is not captured in this version
* your code should consider this issue.
enddo.
*** THE BIG ROUNDUP
* we wait here until ALL splits are returned.
* we do that by waiting until a return counter
* equals the numbers of dispatches.
* this wait does not wait indefinitely if a dispatch above
* fails, since another continue point is NO oustanding
* async tasks.
***
wait until ret_splits >= act_splits.
else.
call function 'Z_CHUNK'
exporting
from_int = 1
to_int = cnt
importing
tot = total.
endif.
get run time field t.
t = t / 1000.
loop at task.
write: / 'Received task', task-taskname, ' at ', task-uzeit, ' in WP:', task-WPINFO-WP_INDEX.
endloop.
write: / 'Parallel', para.
write: / 'Time ms ', t left-justified.
write: / 'Splits ', splits left-justified.
write: / 'Total ', total left-justified.
endform.
*---------------------------------------------------------------------*
* FORM finished *
*---------------------------------------------------------------------*
* ........ *
*---------------------------------------------------------------------*
* --> TASKNAME *
*---------------------------------------------------------------------*
form finished using taskname.
data: ls_wpinfo type WPINFO.
data l_tot type f.
receive results from function 'Z_CHUNK'
importing
tot = l_tot
wp_index = LS_WPINFO-WP_INDEX.
* when receiving a task back, we get out result
* and record that the task returned, by uping a counter.
task-taskname = taskname.
task-uzeit = sy-uzeit.
task-WPINFO = LS_WPINFO.
append task.
total = total + l_tot.
ret_splits = ret_splits + 1.
endform.
*****
* Create this function to test.
FUNCTION Z_CHUNK
IMPORTING
VALUE(FROM_INT) TYPE I
VALUE(TO_INT) TYPE I
EXPORTING
VALUE(TOT) TYPE F
VALUE(WP_INDEX) TYPE WPINFO-WP_INDEX.
data l_i type i.
tot = 0.
check to_int > from_int.
l_i = from_int.
while l_i <= to_int.
tot = tot + l_i.
l_i = l_i + 1.
endwhile.
CALL FUNCTION 'TH_GET_OWN_WP_NO'
IMPORTING
WP_INDEX = WP_INDEX
.
ENDFUNCTION.
Upvotes: -1