So if some other collector already has set its value here, but it has not been picked up by the notification thread, then these events are lost.
If we find that the notify_collector is not-NULL, we need to do something that is correct. So either retry setting it later (so wait on the condition here ... and signal the condition in notification_thread_func. Or have notify_collector a linked list (or even an array) in which we enqueue ourselves.

Even simpler: have all varChangeCollectors add themself on creation in a linked list or array that is afterwards not changed. At this place in the code, we just set a flag in our upnp_var_change_collector_t object that we would like to notify and signal the condition. Whenever the thread wakes up on such a notification, it just goes through all  var change collectors in the list, checking that flag; if it is set, it does the variable sending and resets that flag. Sure, we need to go through all var change collectors for each wakeup ... but that is in the order of three not 10000, so it is an ok choice to make. I think this would be a more robust way to do this.