]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 't/stdin_stdout_fixes'
authorAndre Noll <maan@systemlinux.org>
Tue, 11 Jun 2013 18:41:49 +0000 (20:41 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 11 Jun 2013 18:43:36 +0000 (20:43 +0200)
Was cooking for almost a month.

b99b4a stdin/stdout: Restore fd flags on shutdown.

Conflicts:
stdin.c
stdout.c

NEWS
stdin.c
stdin.h
stdout.c
stdout.h

diff --git a/NEWS b/NEWS
index a93fb2e3315839de57daef32cf5166cd3852579c..07481964e2400d42caeb0db78bf3d66bbbe44509 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@
        - The obsolete gettimeofday() function has been replaced
          by clock_gettime() on systems which support it.
        - Speed and usability improvements for para_gui.
+       - para_client now restores the fd flags of stdin and stdout
+         on shutdown
 
 -----------------------------------------
 0.4.12 (2012-12-20) "volatile relativity"
diff --git a/stdin.c b/stdin.c
index b25a0ba013fb03b19cb757d07ff483c9389a0d70..20b9250e9b7fbf3c252e20dff8891bfeeb5112dd 100644 (file)
--- a/stdin.c
+++ b/stdin.c
@@ -69,6 +69,12 @@ static int stdin_post_select(struct sched *s, struct task *t)
        sz = btr_pool_get_buffer(sit->btrp, &buf);
        if (sz == 0)
                return 0;
+       if (sit->must_set_nonblock_flag) {
+               ret = mark_fd_nonblocking(STDIN_FILENO);
+               if (ret < 0)
+                       goto err;
+               sit->must_set_nonblock_flag = false;
+       }
        /*
         * Do not use the maximal size to avoid having only a single buffer
         * reference for the whole pool. This is bad because if that single
@@ -82,6 +88,8 @@ static int stdin_post_select(struct sched *s, struct task *t)
                return 0;
 err:
        btr_remove_node(&sit->btrn);
+       /* Revert to blocking mode if necessary. */
+       fcntl(STDIN_FILENO, F_SETFL, sit->fd_flags);
        //btr_pool_free(sit->btrp);
        return ret;
 }
@@ -92,8 +100,7 @@ err:
  * \param sit The stdin task structure.
  *
  * This fills in the pre/post select function pointers of the task structure
- * given by \a sit. Moreover, the stdin file desctiptor is set to nonblocking
- * mode, and a buffer tree is created.
+ * given by \a sit and creates a buffer tree for I/O.
  */
 void stdin_set_defaults(struct stdin_task *sit)
 {
@@ -103,9 +110,18 @@ void stdin_set_defaults(struct stdin_task *sit)
        sit->task.post_select = stdin_post_select;
        sit->btrp = btr_pool_new("stdin", 128 * 1024);
        sprintf(sit->task.status, "stdin reader");
-       ret = mark_fd_nonblocking(STDIN_FILENO);
-       if (ret >= 0)
-               return;
-       PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       exit(EXIT_FAILURE);
+       /*
+        * Both STDIN_FILENO and STDOUT_FILENO may refer to the same open file
+        * description (the terminal), and thus share the same file status
+        * flags. In order to not interfere with the stdout task, we only get
+        * the file status flags for STDIN here and save a copy. The nonblock
+        * flag is set later on the first read.
+        */
+       ret = fcntl(STDIN_FILENO, F_GETFL);
+       if (ret < 0) {
+               PARA_EMERG_LOG("F_GETFL: %s\n", strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       sit->fd_flags = ret;
+       sit->must_set_nonblock_flag = (sit->fd_flags & O_NONBLOCK) == 0;
 }
diff --git a/stdin.h b/stdin.h
index 54710ae561105bd7ad0ce907cf078d58d49a80f1..cdf0c67fd57a1078f38a9f175d598adf65ece520 100644 (file)
--- a/stdin.h
+++ b/stdin.h
@@ -14,6 +14,10 @@ struct stdin_task {
        struct btr_node *btrn;
        /** Use a buffer pool to minimize memcpy due to alignment problems. */
        struct btr_pool *btrp;
+       /** The descriptor flags of STDIN at startup. */
+       int fd_flags;
+       /** Whether we have to set STDIN to nonblocking mode. */
+       bool must_set_nonblock_flag;
 };
 
 void stdin_set_defaults(struct stdin_task *sit);
index abf3d06f17a64249671ffbfb0470aa995a599578..cf33bf6d0b67cf49625d27b4d602dec35922d32d 100644 (file)
--- a/stdout.c
+++ b/stdout.c
@@ -62,6 +62,12 @@ static int stdout_post_select(struct sched *s, struct task *t)
        if (!FD_ISSET(STDOUT_FILENO, &s->wfds))
                return 0;
 
+       if (sot->must_set_nonblock_flag) {
+               ret = mark_fd_nonblocking(STDOUT_FILENO);
+               if (ret < 0)
+                       goto out;
+               sot->must_set_nonblock_flag = false;
+       }
        for (;;) {
                sz = btr_next_buffer(btrn, &buf);
                if (sz == 0)
@@ -72,8 +78,11 @@ static int stdout_post_select(struct sched *s, struct task *t)
                btr_consume(btrn, ret);
        }
 out:
-       if (ret < 0)
+       if (ret < 0) {
                btr_remove_node(&sot->btrn);
+               /* Revert to blocking mode if necessary. */
+               fcntl(STDOUT_FILENO, F_SETFL, sot->fd_flags);
+       }
        return ret;
 }
 /**
@@ -82,7 +91,7 @@ out:
  * \param sot The stdout task structure.
  *
  * This fills in the pre/post select function pointers of the task structure
- * given by \a sot and sets the stdout file descriptor to nonblocking mode.
+ * given by \a sot.
  */
 void stdout_set_defaults(struct stdout_task *sot)
 {
@@ -91,9 +100,13 @@ void stdout_set_defaults(struct stdout_task *sot)
        sot->task.pre_select = stdout_pre_select;
        sot->task.post_select = stdout_post_select;
        sprintf(sot->task.status, "stdout");
-       ret = mark_fd_nonblocking(STDOUT_FILENO);
-       if (ret >= 0)
-               return;
-       PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       exit(EXIT_FAILURE);
+
+       /* See stdin.c for details. */
+       ret = fcntl(STDOUT_FILENO, F_GETFL);
+       if (ret < 0) {
+               PARA_EMERG_LOG("F_GETFL: %s\n", strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       sot->fd_flags = ret;
+       sot->must_set_nonblock_flag = (sot->fd_flags & O_NONBLOCK) == 0;
 }
index cc1f2626db049232601375688c8206ba24486177..a21b7cedfb699d9402f666a1a754a26d12cdcec1 100644 (file)
--- a/stdout.h
+++ b/stdout.h
@@ -16,6 +16,10 @@ struct stdout_task {
        struct task task;
        /** Stdout is always a leaf node in the buffer tree. */
        struct btr_node *btrn;
+       /** The descriptor flags of STDOUT at startup. */
+       int fd_flags;
+       /** Whether we have to set STDOUT to nonblocking mode. */
+       bool must_set_nonblock_flag;
 };
 
 void stdout_set_defaults(struct stdout_task *sot);