libURL gone mad

Richard Gaskin ambassador at fourthworld.com
Sat Sep 3 10:43:45 EDT 2016


Charles Warwick wrote:

> If I understand correctly what you are after, how about just arbitrating
> the network requests yourself and then the issue would go away entirely.

So I had thought.  But "GET" and "POST" are handled in an unusual way in 
LC:  they're kinda synchronous, and kinda not, behaving in a 
semi-quasi-threaded way that sometimes makes it difficult to know how to 
work with them.

For example, I like to use functions for things that access data from 
the Internet. As sources of value they fit well with how my code flows.

I often like being able to handle libURL errors returned in "the result" 
generically within the function, leaving any server-side errors returned 
from my CGI to the routine that calls the function.

To handle errors generically within the function, I sometimes show an 
answer dialog, and then "exit to top" - here's a simplified example:

on mouseUp
    put cgiRequest("http://something/on/a/server") into tDataFromServer
    if word 1 of tDataFromServer is "error" then
       -- provide some meaningful feedback based on what the
       -- the server is telling us
    else
       put tDataFromServer into fld "ShowMeWhatsOnTheServer"
    end if
end mouseUp


function cgiRequest pURL
    get url pURL
    put the result into tRequestError
    put it into tDataReturnedFromServer
    --
    -- Check errors reported by libURL:
    if tRequestError is not empty then
       answer "Whoops!  Something went wrong: "& tRequestError
       exit to top  ---< NOTE THIS - we'll discuss it below
    end if
    --
    -- No errors reported, presumably good data:
    return tDataReturnedFromServer
end cgiRequest


With your libURL mod you posted the other day, we can extend that to 
exclude requests being syncblocked as well:

function cgiRequest pURL
    if libUrlIsSyncBlocked() is true then
        answer "Slow down, I'm still working"
        exit to top --< NOTE THIS - see below
    end if
    --
    get url pURL
    put the result into tRequestError
    put it into tDataReturnedFromServer
    --
    -- Check errors reported by libURL:
    if tRequestError is not empty then
       answer "Whoops!  Something went wrong: "& tRequestError
       exit to top  ---< NOTE THIS - we'll discuss it below
    end if
    --
    -- No errors reported, presumably good data:
    return tDataReturnedFromServer
end cgiRequest


In terms of the non-threaded LiveCode we know and love, the above would 
seem logically sound.  Indeed, I use functions, with "exit to top" as 
part of error handling, to access all sorts of values stored in files, 
fields, properties, etc. without issue, allowing me to centralize 
generic error handling while still providing super-simple syntax in my 
libraries for the UI elements that call it.

But in practice, I've found that if I call "exit to top" within a second 
call to a handler that calls libURL, the previous call to libURL never 
completes, and any subsequent calls have no effect.

Even more interestingly, in the second version of the cgiRequest 
function above, "exit to top" can be called before anything in libURL is 
called (if the syncblock is encountered), yet somehow the current libURL 
execution stack from the previous call to that function is still affected.

At some point I can give up and call libUrlResetAll and start over, but 
it's difficult to know in code exactly when I should give up, and I 
really don't like calling libUrlResetAll if I can avoid it since it's a 
fairly deep reset best avoided unless absolutely necessary.

I can use "exit to top" as part of error handling within functions 
safely in just about every other context.

But if used in any handler that calls libURL, it seems to throw off 
previous calls that use libURL, in ways I haven't been able to wrap my 
head around.

It would be possible to rewrite my cgiRequest function as a command, but 
stylistically it's less desirable, and materially it would mean 
rewriting everything in the code base that calls it.

If absolutely necessary, then of course I'd have no choice.  It's 
nothing a cup of coffee and a few hours can't fix. :)

But I'm hoping there's some way to better understand LC's 
semi-quasi-threaded behavior with "GET" and "POST" which would allow me 
to handle errors within a function that accesses a server resource as 
gracefully as I can when accessing just about anything else.

Any tips?


PS: In some cases in my testing I've been able to come up with a 
sequence of calls in which running "GET" through libURL produces no 
value in either "it" or "the result".  This leaves me in the uniquely 
disadvantageous state of having encountered some sort of error without 
any means of knowing it.  That one will take more time to pin down the 
recipe for, but when I do I'll submit a report for it.

-- 
  Richard Gaskin
  Fourth World Systems
  Software Design and Development for the Desktop, Mobile, and the Web
  ____________________________________________________________________
  Ambassador at FourthWorld.com                http://www.FourthWorld.com




More information about the use-livecode mailing list