From 7f1bde6cf42c5e886ec0ba987e1f45aff5ac4486 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Thu, 23 Apr 2009 01:38:55 +0000 Subject: [PATCH] From: lars@segv.dk (Lars Munch) Hi This patch adds two new functions, ecore_pipe_close_read and ecore_pipe_close_write, to ecore_pipe. The purpose it to enable ecore_pipe to be used together with fork (see example below). The patch also handles if the read or write end of the pipe closes. SVN revision: 40305 --- legacy/ecore/src/lib/ecore/Ecore.h | 4 +- legacy/ecore/src/lib/ecore/ecore_pipe.c | 101 +++++++++++++++++++++--- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/legacy/ecore/src/lib/ecore/Ecore.h b/legacy/ecore/src/lib/ecore/Ecore.h index b75178d4ef..7d49239beb 100644 --- a/legacy/ecore/src/lib/ecore/Ecore.h +++ b/legacy/ecore/src/lib/ecore/Ecore.h @@ -294,10 +294,12 @@ extern "C" { EAPI Ecore_Pipe *ecore_pipe_add(void (*handler) (void *data, void *buffer, unsigned int nbyte), const void *data); EAPI void *ecore_pipe_del(Ecore_Pipe *p); EAPI int ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes); + EAPI void ecore_pipe_close_write(Ecore_Pipe *p); + EAPI void ecore_pipe_close_read(Ecore_Pipe *p); EAPI double ecore_time_get(void); EAPI double ecore_loop_time_get(void); - + EAPI Ecore_Timer *ecore_timer_add(double in, int (*func) (void *data), const void *data); EAPI Ecore_Timer *ecore_timer_loop_add(double in, int (*func) (void *data), const void *data); EAPI void *ecore_timer_del(Ecore_Timer *timer); diff --git a/legacy/ecore/src/lib/ecore/ecore_pipe.c b/legacy/ecore/src/lib/ecore/ecore_pipe.c index f6e4778f1a..5608edaf75 100644 --- a/legacy/ecore/src/lib/ecore/ecore_pipe.c +++ b/legacy/ecore/src/lib/ecore/ecore_pipe.c @@ -332,20 +332,68 @@ ecore_pipe_del(Ecore_Pipe *p) "ecore_pipe_del"); return NULL; } - ecore_main_fd_handler_del(p->fd_handler); - close(p->fd_read); - close(p->fd_write); + if(p->fd_handler != NULL) + ecore_main_fd_handler_del(p->fd_handler); + if(p->fd_read != -1) + close(p->fd_read); + if(p->fd_write != -1) + close(p->fd_write); data = (void *)p->data; free (p); return data; } +/** + * Close the read end of an Ecore_Pipe object created with ecore_pipe_add(). + * + * @param p The Ecore_Pipe object. + * @ingroup Ecore_Pipe_Group + */ +EAPI void +ecore_pipe_close_read(Ecore_Pipe *p) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) + { + ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, + "ecore_pipe_close_read"); + return; + } + ecore_main_fd_handler_del(p->fd_handler); + p->fd_handler = NULL; + close(p->fd_read); + p->fd_read = -1; +} + +/** + * Close the write end of an Ecore_Pipe object created with ecore_pipe_add(). + * + * @param p The Ecore_Pipe object. + * @ingroup Ecore_Pipe_Group + */ +EAPI void +ecore_pipe_close_write(Ecore_Pipe *p) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE)) + { + ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, + "ecore_pipe_close_write"); + return; + } + close(p->fd_write); + p->fd_write = -1; +} + /** * Write on the file descriptor the data passed as parameter. * * @param p The Ecore_Pipe object. * @param buffer The data to write into the pipe. * @param nbytes The size of the @p buffer in bytes + * @return Returns TRUE on a successful write, FALSE on an error * @ingroup Ecore_Pipe_Group */ EAPI int @@ -359,9 +407,13 @@ ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes) { ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_write"); - return 0; + return FALSE; } - /* first write the len into the pipe */ + + if(p->fd_write == -1) + return FALSE; + + /* First write the len into the pipe */ do { ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes)); @@ -375,7 +427,13 @@ ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes) /* XXX What should we do here? */ fprintf(stderr, "The length of the data was not written complete" " to the pipe\n"); - return 0; + return FALSE; + } + else if (ret == -1 && errno == EPIPE) + { + close(p->fd_write); + p->fd_write = -1; + return FALSE; } else if (ret == -1 && errno == EINTR) /* try it again */ @@ -390,7 +448,7 @@ ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes) while (retry--); if (retry != ECORE_PIPE_WRITE_RETRY) - return 0; + return FALSE; /* and now pass the data to the pipe */ do @@ -400,12 +458,18 @@ ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes) nbytes - already_written); if (ret == (ssize_t)(nbytes - already_written)) - return 1; + return TRUE; else if (ret >= 0) { already_written -= ret; continue; } + else if (ret == -1 && errno == EPIPE) + { + close(p->fd_write); + p->fd_write = -1; + return FALSE; + } else if (ret == -1 && errno == EINTR) /* try it again */ ; @@ -418,7 +482,7 @@ ecore_pipe_write(Ecore_Pipe *p, const void *buffer, unsigned int nbytes) } while (retry--); - return 0; + return FALSE; } /* Private function */ @@ -453,8 +517,15 @@ _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) fprintf(stderr, "Only read %d bytes from the pipe, although" " we need to read %d bytes.\n", ret, sizeof(p->len)); } - else if ((ret == 0) || - ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN)))) + else if (ret == 0) + { + p->handler((void *)p->data, NULL, 0); + close(p->fd_read); + p->fd_read = -1; + p->fd_handler = NULL; + return ECORE_CALLBACK_CANCEL; + } + else if ((ret == -1) && ((errno == EINTR) || (errno == EAGAIN))) return ECORE_CALLBACK_RENEW; else { @@ -488,6 +559,14 @@ _ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) p->already_read += ret; return ECORE_CALLBACK_RENEW; } + else if (ret == 0) + { + p->handler((void *)p->data, NULL, 0); + close(p->fd_read); + p->fd_read = -1; + p->fd_handler = NULL; + return ECORE_CALLBACK_CANCEL; + } else if (ret == -1 && (errno == EINTR || errno == EAGAIN)) return ECORE_CALLBACK_RENEW; else