Seperate the data event code from the fd handler code in preparation for

fork'n'bitch.


SVN revision: 19876
This commit is contained in:
David Walter Seikel 2006-01-17 11:33:39 +00:00
parent 7ba3cbe1e3
commit 29b4630756
2 changed files with 160 additions and 88 deletions

View File

@ -271,14 +271,20 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
exe = calloc(1, sizeof(Ecore_Exe)); exe = calloc(1, sizeof(Ecore_Exe));
if (exe == NULL) return NULL; if (exe == NULL) return NULL;
if ( (flags & ECORE_EXE_PIPE_AUTO) && (! (flags & ECORE_EXE_PIPE_ERROR)) && (! (flags & ECORE_EXE_PIPE_READ)) )
flags |= ECORE_EXE_PIPE_READ; /* We need something to auto pipe. */
/* Create some pipes. */ /* Create some pipes. */
if (ok) E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) if (ok) E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok)
; ;
if (ok && (flags & ECORE_EXE_PIPE_ERROR)) E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) if (ok && (flags & ECORE_EXE_PIPE_ERROR))
E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok)
exe->child_fd_error = errorPipe[0]; exe->child_fd_error = errorPipe[0];
if (ok && (flags & ECORE_EXE_PIPE_READ)) E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) if (ok && (flags & ECORE_EXE_PIPE_READ))
E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok)
exe->child_fd_read = readPipe[0]; exe->child_fd_read = readPipe[0];
if (ok && (flags & ECORE_EXE_PIPE_WRITE)) E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) if (ok && (flags & ECORE_EXE_PIPE_WRITE))
E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok)
exe->child_fd_write = writePipe[1]; exe->child_fd_write = writePipe[1];
if (ok) if (ok)
@ -522,6 +528,10 @@ ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int st
* more generic designs. It does seem like the closer we get to poll driven, * more generic designs. It does seem like the closer we get to poll driven,
* the more issues and corner cases there are. * the more issues and corner cases there are.
* *
* Instead of doing the usual register an event handler thing, we are ecore_exe,
* we can take some short cuts. Don't send the events, just leave the exe buffers
* as is until the user asks for them, then return the event.
*
* start = 0, end = 0; clogged arteries get flushed, everything is ignored. * start = 0, end = 0; clogged arteries get flushed, everything is ignored.
* start = -1, end = -1; clogged arteries get transferred to internal buffers. Actually, either == -1 means buffer everything. * start = -1, end = -1; clogged arteries get transferred to internal buffers. Actually, either == -1 means buffer everything.
* start = X, end = 0; buffer first X out of clogged arteries, flush and ignore rest. * start = X, end = 0; buffer first X out of clogged arteries, flush and ignore rest.
@ -532,6 +542,7 @@ ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int st
* *
* Other issues - * Other issues -
* Spank programmer for polling data if polling is not turned on. * Spank programmer for polling data if polling is not turned on.
* Spank programmer for setting up event callbacks if polling is turned on.
* Spank programmer for freeing the event data if it came from the event system, as that autofrees. * Spank programmer for freeing the event data if it came from the event system, as that autofrees.
* Spank the programmer if they try to set the limits bigger than what has been gathered & ignored already, coz they just lost data. * Spank the programmer if they try to set the limits bigger than what has been gathered & ignored already, coz they just lost data.
* Spank onefang and raster for opening this can of worms. * Spank onefang and raster for opening this can of worms.
@ -1048,38 +1059,29 @@ _ecore_exe_exec_it(const char *exe_cmd)
return; return;
} }
static int static Ecore_Exe_Event_Data *
_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags) _ecore_exe_create_event_data(Ecore_Exe *exe, Ecore_Fd_Handler_Flags flags)
{ {
Ecore_Exe *exe; Ecore_Exe_Event_Data *e = NULL;
int child_fd;
int is_buffered = 0; int is_buffered = 0;
int event_type; unsigned char *inbuf;
int inbuf_num;
exe = data; /* Sort out what sort of event we are. */
if (flags & ECORE_FD_READ) if (flags & ECORE_FD_READ)
{ {
flags = ECORE_FD_READ; flags = ECORE_FD_READ;
event_type = ECORE_EXE_EVENT_DATA;
child_fd = exe->child_fd_read;
if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED) if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
is_buffered = 1; is_buffered = 1;
} }
else else
{ {
flags = ECORE_FD_ERROR; flags = ECORE_FD_ERROR;
event_type = ECORE_EXE_EVENT_ERROR;
child_fd = exe->child_fd_error;
if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED) if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
is_buffered = 1; is_buffered = 1;
} }
if ((fd_handler) && (ecore_main_fd_handler_active_get(fd_handler, flags))) /* Get the data. */
{
unsigned char *inbuf;
int inbuf_num;
/* Get any left over data from last time. */
if (flags & ECORE_FD_READ) if (flags & ECORE_FD_READ)
{ {
inbuf = exe->read_data_buf; inbuf = exe->read_data_buf;
@ -1095,35 +1097,6 @@ _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_
exe->error_data_size = 0; exe->error_data_size = 0;
} }
for (;;)
{
int num, lost_exe;
char buf[READBUFSIZ];
lost_exe = 0;
errno = 0;
if ((num = read(child_fd, buf, READBUFSIZ)) < 1) /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE (currently 64k) to inbuf, use that instead of buf, and save ourselves a memcpy(). */
{
lost_exe = ((errno == EIO) ||
(errno == EBADF) ||
(errno == EPIPE) ||
(errno == EINVAL) ||
(errno == ENOSPC));
if ((errno != EAGAIN) && (errno != EINTR))
perror("_ecore_exe_generic_handler() read problem ");
}
if (num > 0)
{ /* data got read. */
inbuf = realloc(inbuf, inbuf_num + num);
memcpy(inbuf + inbuf_num, buf, num);
inbuf_num += num;
}
else
{ /* No more data to read. */
if (inbuf)
{
Ecore_Exe_Event_Data *e;
e = calloc(1, sizeof(Ecore_Exe_Event_Data)); e = calloc(1, sizeof(Ecore_Exe_Event_Data));
if (e) if (e)
{ {
@ -1199,7 +1172,104 @@ _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_
} }
} }
} }
}
return e;
}
static int
_ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
{
Ecore_Exe *exe;
int child_fd;
int is_buffered = 0;
int event_type;
exe = data;
/* Sort out what sort of handler we are. */
if (flags & ECORE_FD_READ)
{
flags = ECORE_FD_READ;
event_type = ECORE_EXE_EVENT_DATA;
child_fd = exe->child_fd_read;
if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
is_buffered = 1;
}
else
{
flags = ECORE_FD_ERROR;
event_type = ECORE_EXE_EVENT_ERROR;
child_fd = exe->child_fd_error;
if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
is_buffered = 1;
}
if ((fd_handler) && (ecore_main_fd_handler_active_get(fd_handler, flags)))
{
unsigned char *inbuf;
int inbuf_num;
/* Get any left over data from last time. */
if (flags & ECORE_FD_READ)
{
inbuf = exe->read_data_buf;
inbuf_num = exe->read_data_size;
exe->read_data_buf = NULL;
exe->read_data_size = 0;
}
else
{
inbuf = exe->error_data_buf;
inbuf_num = exe->error_data_size;
exe->error_data_buf = NULL;
exe->error_data_size = 0;
}
for (;;)
{
int num, lost_exe;
char buf[READBUFSIZ];
lost_exe = 0;
errno = 0;
if ((num = read(child_fd, buf, READBUFSIZ)) < 1) /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE (currently 64k) to inbuf, use that instead of buf, and save ourselves a memcpy(). */
{
lost_exe = ((errno == EIO) ||
(errno == EBADF) ||
(errno == EPIPE) ||
(errno == EINVAL) ||
(errno == ENOSPC));
if ((errno != EAGAIN) && (errno != EINTR))
perror("_ecore_exe_generic_handler() read problem ");
}
if (num > 0)
{ /* data got read. */
inbuf = realloc(inbuf, inbuf_num + num);
memcpy(inbuf + inbuf_num, buf, num);
inbuf_num += num;
}
else
{ /* No more data to read. */
if (inbuf)
{
Ecore_Exe_Event_Data *e;
/* Stash the data away for later. */
if (flags & ECORE_FD_READ)
{
exe->read_data_buf = inbuf;
exe->read_data_size = inbuf_num;
}
else
{
exe->error_data_buf = inbuf ;
exe->error_data_size = inbuf_num;
}
if (! (exe->flags & ECORE_EXE_PIPE_AUTO))
{
e = _ecore_exe_create_event_data(exe, flags);
if (e) /* Send the event. */ if (e) /* Send the event. */
ecore_event_add(event_type, e, ecore_event_add(event_type, e,
_ecore_exe_event_exe_data_free, NULL); _ecore_exe_event_exe_data_free, NULL);
@ -1222,7 +1292,7 @@ _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler *fd_handler, Ecore_
* recently and the pid has not had a chance to recycle. * recently and the pid has not had a chance to recycle.
* It is also a paranoid catchall, coz the usual ecore_signal * It is also a paranoid catchall, coz the usual ecore_signal
* mechenism should kick in. But let's give it a good * mechenism should kick in. But let's give it a good
* kick anyway. * kick in the head anyway.
*/ */
ecore_exe_terminate(exe); ecore_exe_terminate(exe);
} }
@ -1354,4 +1424,5 @@ _ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
if (e->exe) ecore_exe_free(e->exe); if (e->exe) ecore_exe_free(e->exe);
free(e); free(e);
} }
#endif #endif

View File

@ -156,7 +156,8 @@ enum _Ecore_Exe_Flags
ECORE_EXE_PIPE_ERROR = 4, ECORE_EXE_PIPE_ERROR = 4,
ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8,
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16,
ECORE_EXE_RESPAWN = 32 ECORE_EXE_PIPE_AUTO = 32,
ECORE_EXE_RESPAWN = 64
/* FIXME: Getting respawn to work /* FIXME: Getting respawn to work
* *
* There is no way that we can do anything about the internal state info of * There is no way that we can do anything about the internal state info of