Clear the values of pipe before calling handler.
authorRyuan Choi <ryuan.choi@samsung.com>
Fri, 25 Apr 2014 01:29:01 +0000 (10:29 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Fri, 25 Apr 2014 01:29:01 +0000 (10:29 +0900)
Summary:
Applications are stuck when handler of pipe made nested loop.
In the nested loop, _ecore_pipe_read() tried to read new data based on previous information which is not cleared yet.

Spotted by gyuyoung.kim, sy302.park.

Related webkit bug is https://bugs.webkit.org/show_bug.cgi?id=129294

Reviewers: cedric, seoz, raster

CC: seoz, cedric
Differential Revision: https://phab.enlightenment.org/D790

src/lib/ecore/ecore_pipe.c

index 705673b..9783c2f 100644 (file)
@@ -586,12 +586,22 @@ _ecore_pipe_handler_call(Ecore_Pipe *p,
                          size_t len)
 {
    void *data = (void*) p->data;
+
+   // clear all values of pipe first.
+   p->passed_data = NULL;
+   p->already_read = 0;
+   p->len = 0;
+   p->message++;
+
    if (!p->delete_me)
      {
         _ecore_unlock();
         p->handler(data, buf, len);
         _ecore_lock();
      }
+
+   // free p->passed_data
+   free(buf);
 }
 
 static Eina_Bool
@@ -634,11 +644,6 @@ _ecore_pipe_read(void             *data,
                       {
      /* no data on first try through means an error */
                           _ecore_pipe_handler_call(p, NULL, 0);
-                          if (p->passed_data) free(p->passed_data);
-                          p->passed_data = NULL;
-                          p->already_read = 0;
-                          p->len = 0;
-                          p->message++;
                           pipe_close(p->fd_read);
                           p->fd_read = PIPE_FD_INVALID;
                           p->fd_handler = NULL;
@@ -673,11 +678,6 @@ _ecore_pipe_read(void             *data,
                    if (WSAGetLastError() != WSAEWOULDBLOCK)
                      {
                         _ecore_pipe_handler_call(p, NULL, 0);
-                        if (p->passed_data) free(p->passed_data);
-                        p->passed_data = NULL;
-                        p->already_read = 0;
-                        p->len = 0;
-                        p->message++;
                         pipe_close(p->fd_read);
                         p->fd_read = PIPE_FD_INVALID;
                         p->fd_handler = NULL;
@@ -694,12 +694,6 @@ _ecore_pipe_read(void             *data,
         if (p->len == 0)
           {
              _ecore_pipe_handler_call(p, NULL, 0);
-             /* reset all values to 0 */
-             if (p->passed_data) free(p->passed_data);
-             p->passed_data = NULL;
-             p->already_read = 0;
-             p->len = 0;
-             p->message++;
              _ecore_pipe_unhandle(p);
              return ECORE_CALLBACK_RENEW;
           }
@@ -713,9 +707,6 @@ _ecore_pipe_read(void             *data,
                {
                   _ecore_pipe_handler_call(p, NULL, 0);
      /* close the pipe */
-                  p->already_read = 0;
-                  p->len = 0;
-                  p->message++;
                   pipe_close(p->fd_read);
                   p->fd_read = PIPE_FD_INVALID;
                   p->fd_handler = NULL;
@@ -732,15 +723,7 @@ _ecore_pipe_read(void             *data,
         /* catch the non error case first */
         /* if we read enough data to finish the message/buffer */
         if (ret == (ssize_t)(p->len - p->already_read))
-          {
-             _ecore_pipe_handler_call(p, p->passed_data, p->len);
-             free(p->passed_data);
-             /* reset all values to 0 */
-             p->passed_data = NULL;
-             p->already_read = 0;
-             p->len = 0;
-             p->message++;
-          }
+          _ecore_pipe_handler_call(p, p->passed_data, p->len);
         else if (ret > 0)
           {
              /* more data left to read */
@@ -775,11 +758,6 @@ _ecore_pipe_read(void             *data,
              if (WSAGetLastError() != WSAEWOULDBLOCK)
                {
                   _ecore_pipe_handler_call(p, NULL, 0);
-                  if (p->passed_data) free(p->passed_data);
-                  p->passed_data = NULL;
-                  p->already_read = 0;
-                  p->len = 0;
-                  p->message++;
                   pipe_close(p->fd_read);
                   p->fd_read = PIPE_FD_INVALID;
                   p->fd_handler = NULL;