diff --git a/qemu-nbd.c b/qemu-nbd.c
index e76c782..6a84cde 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -32,6 +32,7 @@
 #include <signal.h>
 #include <libgen.h>
 #include <pthread.h>
+#include <sys/wait.h>
 
 #define SOCKET_PATH    "/var/lock/qemu-nbd-%s"
 
@@ -415,54 +416,58 @@ int main(int argc, char **argv)
     }
 
     if (device && !verbose) {
-        int stderr_fd[2];
+        int cpipe[2];
         pid_t pid;
-        int ret;
 
-        if (qemu_pipe(stderr_fd) == -1) {
+        if (qemu_pipe(cpipe) == -1) {
             err(EXIT_FAILURE, "Error setting up communication pipe");
         }
 
         /* Now daemonize, but keep a communication channel open to
-         * print errors and exit with the proper status code.
+         * pass errors.
          */
         pid = fork();
         if (pid == 0) {
-            close(stderr_fd[0]);
-            ret = qemu_daemon(0, 0);
-
-            /* Temporarily redirect stderr to the parent's pipe...  */
-            dup2(stderr_fd[1], STDERR_FILENO);
-            if (ret == -1) {
+            int nullfd = open("/dev/null", O_RDWR);
+            if (nullfd < 0 || setsid() < 0) {
                 err(EXIT_FAILURE, "Failed to daemonize");
             }
-
-            /* ... close the descriptor we inherited and go on.  */
-            close(stderr_fd[1]);
-        } else {
-            bool errors = false;
-            char *buf;
-
-            /* In the parent.  Print error messages from the child until
-             * it closes the pipe.
+            /* redirect stdin from /dev/null,
+             * stdout (temporarily) to the pipe to parent,
+             * and keep stderr for error report.
+             * When initializing is done, redirect stdout and stderr
+             * to /dev/null (stdin).
              */
-            close(stderr_fd[1]);
-            buf = g_malloc(1024);
-            while ((ret = read(stderr_fd[0], buf, 1024)) > 0) {
-                errors = true;
-                ret = qemu_write_full(STDERR_FILENO, buf, ret);
-                if (ret == -1) {
-                    exit(EXIT_FAILURE);
-                }
+            if (nullfd != STDIN_FILENO) {
+                dup2(nullfd, STDIN_FILENO);
+                close(nullfd);
             }
-            if (ret == -1) {
-                err(EXIT_FAILURE, "Cannot read from daemon");
+            close(cpipe[0]);
+            if (cpipe[1] != STDOUT_FILENO) {
+                dup2(cpipe[1], STDOUT_FILENO);
+                close(cpipe[1]);
             }
-
-            /* Usually the daemon should not print any message.
-             * Exit with zero status in that case.
+        } else if (pid < 0) {
+            err(EXIT_FAILURE, "Failed to daemonize");
+        } else {
+            close(cpipe[1]);
+            /* In parent, just a dummy read till the pipe gets closed.
+             * When it does, check process exit status using waitpid().
              */
-            exit(errors);
+            ret = read(cpipe[0], &ret, sizeof(ret));
+            pid = waitpid(pid, &ret, WNOHANG);
+            if (pid < 0) {
+                err(EXIT_FAILURE, "Cannot read from daemon");
+            }
+            return
+              /* waitpid(pid, WNOHANG) returns 0 if the process
+               * in question did not change state. In this case
+               * we assume our child successfully initialized and
+               * is now running, so exit succcessfully here.
+               */
+              pid == 0 ? 0 :
+              /* else our child exited, so return its exit status */
+              WIFEXITED(ret) ? WEXITSTATUS(ret) : 1;
         }
     }
 
@@ -527,6 +532,18 @@ int main(int argc, char **argv)
     qemu_set_fd_handler2(sockfd, nbd_can_accept, nbd_accept, NULL,
                          (void *)(uintptr_t)sockfd);
 
+    /* now complete the daemonizing procedure.
+     */
+    if (device && !verbose) {
+        if (chdir("/") < 0) {
+            err(EXIT_FAILURE, "unable to chdir to /");
+        }
+        /* this redirects stderr to /dev/null */
+        dup2(STDIN_FILENO, STDERR_FILENO);
+        /* this redirects stdout to /dev/null too, and closes parent pipe */
+        dup2(STDIN_FILENO, STDOUT_FILENO);
+    }
+
     do {
         main_loop_wait(false);
     } while (!sigterm_reported && (persistent || !nbd_started || nb_fds > 0));
