I suggest that you modify the msgrcv call so that it is non-blocking - you can obtain that by passing IPC_NOWAIT as one of the flags. This way the call will return immediately even if no message is waiting in the queue. It will then set errno to ENOMSG. Then you'll be able to repeat the call after some time to see if something entered the queue in the meantime.

If you insist on using signals, I'd suggest sending SIGALRM instead... You have to mask signals you don't want to intercept in each thread (man sigprocmask is your friend). Then you can hope the appropriate thread receives it.