Results 1 to 7 of 7

Thread: Stuck in recv function

  1. #1
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default Stuck in recv function

    Recently i have been having problem loading RS (in both browser and SMART), requiring multiple tries to load successfully. So i'm trying to setup a loop in SMART so that it auto retry for me when failed to spawn.
    After some debugging, i confirmed that it's stuck in https://github.com/BenLand100/SMART/...emote.cpp#L131
    So i split the code from line130 onwards into
    C++ Code:
    int sel = select(client->socket+1, &rfds, &rfds, NULL, &tv);
            if (sel) {
                debug << sel << endl;
                SOCKET s = client->socket;
                char* buf = (char*)&funid;
                int len = sizeof(char);
                debug << "s: " << s << " buf: " << *buf << " len: " << len << endl;
                int intRecv = recv(s, buf, len, 0);

    However, the values returned for both failed attempts and successful attempts appear to be the same.
    sel is always 1, *buf is always 'I', len is always 1, only s varies from ~1150 to 1250.

    So how could i predetermine if it's going to fail or pass so that if it's going to fail i wouldn't go into recv() and get stuck inside?
    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    Changing the flags argument didn't help too.

  2. #2
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    Recently i have been having problem loading RS (in both browser and SMART), requiring multiple tries to load successfully. So i'm trying to setup a loop in SMART so that it auto retry for me when failed to spawn.
    After some debugging, i confirmed that it's stuck in https://github.com/BenLand100/SMART/...emote.cpp#L131
    So i split the code from line130 onwards into
    C++ Code:
    int sel = select(client->socket+1, &rfds, &rfds, NULL, &tv);
            if (sel) {
                debug << sel << endl;
                SOCKET s = client->socket;
                char* buf = (char*)&funid;
                int len = sizeof(char);
                debug << "s: " << s << " buf: " << *buf << " len: " << len << endl;
                int intRecv = recv(s, buf, len, 0);

    However, the values returned for both failed attempts and successful attempts appear to be the same.
    sel is always 1, *buf is always 'I', len is always 1, only s varies from ~1150 to 1250.

    So how could i predetermine if it's going to fail or pass so that if it's going to fail i wouldn't go into recv() and get stuck inside?
    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    Changing the flags argument didn't help too.
    I don't know FPC details, but as I recall select() returns -1/0/1 or the number of ready file descriptors. Maybe that test in there should be 'if (sel > 0)'

  3. #3
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    I don't know FPC details, but as I recall select() returns -1/0/1 or the number of ready file descriptors. Maybe that test in there should be 'if (sel > 0)'
    The code is C++ not FP
    Anyway sel returns 1 both when Smart successfully spawned and when Smart failed to spawn (stuck in recv), so i think i'd need some other tests other than select() to determine if it will be stuck in recv.
    @Brandon; any idea?

  4. #4
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by riwu View Post
    The code is C++ not FP
    Anyway sel returns 1 both when Smart successfully spawned and when Smart failed to spawn (stuck in recv), so i think i'd need some other tests other than select() to determine if it will be stuck in recv.
    @Brandon; any idea?
    Ehehe, I need to stop posting at wake-up time. Yes, I see this is C code

    I stick to my claim that the test is flawed. Only if select() > 0 is a socket ready. I understand you're saying it is getting a '1' response in this case but sometime it will get SOCKET_ERROR and bug out.

    Code:
    select(client->socket+1, &rfds, &rfds, NULL, &tv);
    Notice &rfds is passed as both the readfds and writefds. Select() can return '1' if this socket is writeble. Not readable. Then your read would hang.

    I'm going to suggest trying this:

    Code:
    select(client->socket+1, &rfds, NULL, NULL, &tv);

  5. #5
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    Ehehe, I need to stop posting at wake-up time. Yes, I see this is C code

    I stick to my claim that the test is flawed. Only if select() > 0 is a socket ready. I understand you're saying it is getting a '1' response in this case but sometime it will get SOCKET_ERROR and bug out.

    Code:
    select(client->socket+1, &rfds, &rfds, NULL, &tv);
    Notice &rfds is passed as both the readfds and writefds. Select() can return '1' if this socket is writeble. Not readable. Then your read would hang.

    I'm going to suggest trying this:

    Code:
    select(client->socket+1, &rfds, NULL, NULL, &tv);
    Hmm you are right that it is returning 1 even though it's not readable (only writable). I thought when u supply arguments to both, it will check and return 1 only if it is both readable and writable, otherwise kind of defeats the purpose of using optional parameters...

    Though when i set it to check readable only, it always returns -1, even when the client successfully spawned...
    So there's still no test to check whether the call to recv will be blocked.

  6. #6
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    C++ Code:
    int CheckSocket(int sock, long sec, long usec, bool Read)
    {
        fd_set fds = {0};
        struct timeval tv = {0};
        FD_ZERO(&fds);
        FD_SET(sock, &fds);
        tv.tv_sec = sec;
        tv.tv_usec = usec;
        return select(sock + 1, Read ? &fds : NULL, Read ? NULL : &fds, NULL, &tv);
    }


    #if defined _WIN32 || defined _WIN64
    std::string LastErrorMessage()
    {
        DWORD Error = GetLastError();
        LPTSTR lpMsgBuf = nullptr;
        FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
        std::string result = std::string(lpMsgBuf);
        LocalFree(lpMsgBuf);
        return result;
    }
    #else
    std::string LastErrorMessage()
    {
        return std::string(strerror(errno));
    }
    #endif



    Then call:

    C++ Code:
    for (int i = 0; i < 600; ++i)
    {
        int sel = CheckSocket(client->socket + 1, 0, 100000, true);  //100ms time-out on read.
        if (sel > 0) //If the socket is ready to be read and != SOCKET_ERROR aka -1.
        {
            if (recv(client->socket, (char*)&funid, sizeof(char), 0) != sizeof(char))
            {
                debug << "Call appears to have failed, or client successfully killed.\n";
                debug << "Last Error: "<<LastErrorMessage()<<"\n"; //Print failure in proper format..
            }
            return;
        }
    }
    Last edited by Brandon; 01-18-2015 at 04:49 PM.
    I am Ggzz..
    Hackintosher

  7. #7
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Thanks Brandon!
    Had to add -std=c++0x to g++ build dir in MAKEFILE to get it to compile (nullptr keyword)

    Seems like Jagex already fixed the problem though
    http://services.runescape.com/m=news...jptv=news_list

    Will see if it works if it happens again

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •