+ }
+out_crashed:
+ ERROR("The filesystem daemon has crashed! Changes to the "
+ "WIM may not have been commited.");
+ return WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED;
+}
+
+static int
+daemon_timed_out_cb(void *_handler_ctx)
+{
+ ERROR("Timed out waiting for unmount request! "
+ "Changes to the mounted WIM will not be committed.");
+ return WIMLIB_ERR_TIMEOUT;
+}
+
+typedef int (*msg_handler_t)(const void *_msg, void *_handler_ctx);
+
+struct msg_handler_callbacks {
+ int (*timed_out)(void * _handler_ctx);
+ msg_handler_t msg_handlers[MSG_TYPE_MAX];
+};
+
+static const struct msg_handler_callbacks unmount_msg_handler_callbacks = {
+ .timed_out = unmount_timed_out_cb,
+ .msg_handlers = {
+ [MSG_TYPE_DAEMON_INFO] = msg_daemon_info_handler,
+ [MSG_TYPE_WRITE_STREAMS_PROGRESS] = msg_write_streams_progress_handler,
+ [MSG_TYPE_UNMOUNT_FINISHED] = msg_unmount_finished_handler,
+ },
+};
+
+static const struct msg_handler_callbacks daemon_msg_handler_callbacks = {
+ .timed_out = daemon_timed_out_cb,
+ .msg_handlers = {
+ [MSG_TYPE_UNMOUNT_REQUEST] = msg_unmount_request_handler,
+ },
+};
+
+static int
+receive_message(mqd_t mq,
+ struct msg_handler_context_hdr *handler_ctx,
+ const msg_handler_t msg_handlers[],
+ long mailbox_size, void *mailbox)
+{
+ struct timeval now;
+ struct timespec timeout;
+ ssize_t bytes_received;
+ struct unmount_msg_hdr *hdr;
+ int ret;
+
+ gettimeofday(&now, NULL);
+ timeout.tv_sec = now.tv_sec + handler_ctx->timeout_seconds;
+ timeout.tv_nsec = now.tv_usec * 1000;
+
+ bytes_received = mq_timedreceive(mq, mailbox,
+ mailbox_size, NULL, &timeout);
+ hdr = mailbox;
+ if (bytes_received == -1) {
+ if (errno == ETIMEDOUT) {
+ ret = WIMLIB_ERR_TIMEOUT;