Why do you want to avoid fork/threads?
You have two choices:
- Do the actual processing in an external child process, and tell every client to check back in 5 minutes to get their new status (wait again, or done)
- Implement nonblocking sockets and poll them, for example using Coro