Error message 2780 Workaraound?

enoon

Member
I'm experiencing problems with a WAIT-FOR statement.
There is a CLASS that has a method that runs persistently a procedure. The procedure calls a second procedure that does a WAIT-FOR statement.
The error at runtime is "Input blocking statement is invalid while executing a user-defined function or method: 'F21'. (2780)".
The last procedure reads some data from a server, and it cannot be left out.
Anyone encountered this problem, how did you solve it?

Thanks in advance.
 
Having a WAIT-FOR statemnet in an internal function or a procedure or a method of a class is not allowed and therefore you get the error message. I am not aware of a workaround.

It would be interresting to know for what you need the WAIT-FOR in some a procedure which is called from a persistent procedure which is persistently started from a method in a class in the first place. Maybe you should re-think your design.

As far as my experience goes - mixing OOABL with GUI, e.g. starting GUI windows which have WAIT-FORs from a class, is very tricky.

HTH, RealHeavyDude.
 
Oh yes indeed, we found out the problem.
We use DATASETS to simulate Reflexion in our OO mini framework:
dsPar:set-callback("before-fill", methodName, THIS-OBJECT).
dsPar:apply-callback("before-fill").
And any method passed through this (methodName), even if it is a VOID one, messes up the AVM, and throws this error. If a normal VOID method is called withouth the set-callback the code works as expected.
We will leave this for now, as we have other test/bugfixes, I will be back with more infor if we found something, and anyone is interested in this topic.

Other OO faults:
- CAN-FIND gives a SYSTEM BUS ERROR when used in method call as a parameter.
- Buffer defined in super class lets say bCustomer, in inherited class same bCustomer defined in a method gives also a SYSTEM BUS ERROR. (I know it is a stupid error, but we generated the OO classes from a repository)
- using BIND-ing to simulate SHARED TEMP-TABLE does now work if table used in a 2nd level inheritance. (CLASS A uses temp-table, inherits B, and B inherits C where it is bound)

Cheers.
 
It would be interresting to know for what you need the WAIT-FOR in some a procedure which is called from a persistent procedure which is persistently started from a method in a class in the first place. Maybe you should re-think your design.

Purpose of our project was: generate from a repository a completely rewritten framework/application to OO structure. We got 99% of it done, there are few situations like this that needs to be resolved.
Any idea on how to do this?

We found something, but the code does not work.
We got a:
PAUSE 1 NO-MESSAGE.

instead of:
WAIT-FOR READ-RESPONSE OF hSocket PAUSE 1.

The story goes like this: an object, loads persistent a library, the library does run the "problematic procedure" which has the WAIT-FOR statement. The procedure creates a socket, connects to a server and writes something to that socket. In the main block it waits for response. But nothing comes (with the new PAUSE statement) so the connection is timed out.
:confused:

Code:
DEFINE INPUT  PARAMETER picServer    AS CHARACTER  NO-UNDO.
DEFINE INPUT  PARAMETER picSocket    AS CHARACTER  NO-UNDO.
DEFINE INPUT  PARAMETER picRequest   AS CHARACTER  NO-UNDO.
DEFINE OUTPUT PARAMETER pocResponce  AS CHARACTER  NO-UNDO.

DEFINE VARIABLE hSocket           AS HANDLE     NO-UNDO.
DEFINE VARIABLE lCompleetBericht  AS LOGICAL    NO-UNDO.
DEFINE VARIABLE iStartMoment      AS INTEGER    NO-UNDO.
DEFINE VARIABLE lConnected        AS LOGICAL    NO-UNDO.
DEFINE VARIABLE mBuffer           AS MEMPTR     NO-UNDO.

/********** End Main variables section **********/

/************ Main initialisation section ************/
CREATE SOCKET hSocket.

ASSIGN iStartMoment  = TIME
       pocResponce   = "" 
       lConnected    = FALSE
       lConnected    = hSocket:CONNECT(" -H " + 
                                       picServer + 
                                       " -S " + 
                                       picSocket)
       NO-ERROR.

IF NOT lConnected
THEN DO:
   ASSIGN pocResponce = ?.
END. /* IF NOT lConnected */
ELSE DO: /* ELSE IF NOT lConnected */
    
   hSocket:SET-READ-RESPONSE-PROCEDURE( "leesSocket", THIS-PROCEDURE ).

   ASSIGN SET-SIZE(mBuffer)     = 0
          SET-SIZE(mBuffer)     = LENGTH(picRequest) + 1
          PUT-STRING(mBuffer,1) = picrequest
          .
   hSocket:WRITE(mBuffer, 1, LENGTH(picRequest)).

   MAIN-BLOCK:
   REPEAT:
      
      /* this does not work anymore when called from a method returning other type than VOID
      WAIT-FOR READ-RESPONSE OF hSocket PAUSE 1.
      */
      PAUSE 1 NO-MESSAGE. /* this does not work either */
      
      IF    lCompleetBericht 
         OR TIME - iStartMoment > 35
         OR TIME - iStartMoment < 0
      THEN LEAVE.
   END.

   IF pocResponce = ""
   THEN DO:
      IF hSocket:CONNECTED()
      THEN hSocket:DISCONNECT().
      DELETE OBJECT hSocket NO-ERROR.

      RETURN ERROR "Connection responce timed out".
   END.

   IF hSocket:CONNECTED()
   THEN DO: 
      hSocket:DISCONNECT().
   END.
   DELETE OBJECT hSocket NO-ERROR.

END. /* ELSE IF NOT lConnected */

IF NOT lConnected
THEN DO:
   RETURN ERROR "Connection Failed".
END. /* IF NOT lConnected */

/********** End Main initialisation section **********/

PROCEDURE leesSocket:
   DEFINE VARIABLE iKarakters   AS INTEGER    NO-UNDO.
   DEFINE VARIABLE cTemp        AS CHARACTER  NO-UNDO.
   DEFINE VARIABLE mBuffer      AS MEMPTR     NO-UNDO.
   
   ASSIGN iKarakters = hSocket:GET-BYTES-AVAILABLE()
          cTemp      = ""
          .
   IF iKarakters > 0 
   THEN DO:
      ASSIGN SET-SIZE(mBuffer) = iKarakters + 1
             .
      hSocket:READ(mBuffer, 1, iKarakters, 1).
      ASSIGN cTemp             = GET-STRING(mBuffer,1)
             pocResponce       = pocResponce + cTemp
             SET-SIZE(mBuffer) = 0.
   END.
   IF iKarakters = 0
   THEN DO:
       ASSIGN lCompleetBericht = TRUE.
   END.
END PROCEDURE. /* leesSocket */
 
I am not very experienced with socket programming in the 4GL, but maybe the PROCESS EVENTS statement might aid to solve the problem.

HTH, RealHeavyDude.
 
Thanks for the suggestion.
Finally we got it working, the solution is, replacing the READ-RESPONSE trigger with an instruction on the handle GET-BYTES-AVAILABLE:

Instead of:

Code:
       WAIT-FOR READ-RESPONSE OF hSocket PAUSE 1.

We can use (to have the same behavior and trick the 2780 error message):

Code:
      IF hSocket:GET-BYTES-AVAILABLE() > 0
      THEN DO: /* if data available, then read */
          RUN leesSocket.
          lRead = TRUE.
          END.
      ELSE DO: /* if no data, then wait for incoming data */
          IF NOT lRead 
          THEN PAUSE 1 NO-MESSAGE.
          ELSE lCompleetBericht = TRUE.
      END.
 
Back
Top