5

Is there a way to call a function, and then cancel or skip over the call if it takes too long to respond?

I'm simulating an ftp connection, and I'm receiving a response from a server using this function call:

status = receiveMessage(ccSocket, replyMsg, sizeof(replyMsg), &msgSize);

Is there a way to wait, say, 5 seconds, and skip over the function call if it has not yet responded?

Matt123
  • 556
  • 3
  • 15
  • 36

3 Answers3

5

Many different methods are available for you to solve this problem.

  1. Using a "select" call, allow your system to check if there is data available, using a given timeout which allows you to cancel the check if it takes to long.
  2. Asynchronous design enables you to "watch" a socket without ever having to "wait" on that socket, meaning your process is only ever run when it is known that data is available 3
  3. Non-Blocking design allows you to use your processor for many different reasons, where a communication on a socket should not hold your processor up, similar is a way, to Async comms, but with a small twist
Patrick Sturm
  • 393
  • 1
  • 13
1

Depends on a function and how much control you have over it.

In case of recv call you could use setsocketopt with SO_RCVTIMEO to set the timeout. The function call would return EAGAIN or EWOULDBLOCK in that case.

Alternatively, you could interrupt the recv call - the ways to do it are described at How to cleanly interrupt a thread blocking on a recv call?

In a more generic case, you could have start a parallel thread, and have both of them threads keep a reference to a boolean value that would mark if the timeout had expired. The original thread doing the work would need to periodically check it, and the other one would mark it after timeout has passed. If the function call finishes before the timeout, it would be main thread's responsibility to shutdown the helper.

In pseudocode it would look like this:

shared mutable state:

job_to_do = true
timeout_happened = false

main thread:

pthread_create(helper, ...)
/* we depend on the fact that 'job_to_do' will be set to false when there's nothing more to process */
while (job_to_do && !timeout_happened) {
    process_more_for_some_time /* this obviously has to take less time than timeout */
}
if (job_to_do) {
    perror("timeout")
}

helper thread:

time_passed = 0
while (job_to_do && time_passed < timeout) {
    sleep(sample)
    time_passed += sample
}
/* there's no point in signalling timeout if the job has finished */
if (job_to_do)
    timeout_happened = true

Implementation detail: job_to_do and timeout_happened have to be atomic/visible, as you could be e.g. accessing the variable from different cores.

Adam Kotwasinski
  • 4,377
  • 3
  • 17
  • 40
1
  1. you can check if you have a watchdog in the system and use it

  2. set a timer interrupt to be called each 3 seconds and set a global variable STOP=true inside its handler

  3. in your big code put if (STOP) exit(1).

alinsoar
  • 15,386
  • 4
  • 57
  • 74