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.