forked from enlightenment/efl
* exe exit event delay method changed.
* Added method to close an exe's stdin in a (probably) vain attempt to convince exe to exit. * Other debugging shit. SVN revision: 19430
This commit is contained in:
parent
e37b4166d8
commit
8bb13800f8
|
@ -210,6 +210,7 @@ extern "C" {
|
|||
EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data);
|
||||
EAPI Ecore_Exe *ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data);
|
||||
EAPI int ecore_exe_pipe_write(Ecore_Exe *exe, void *data, int size);
|
||||
EAPI void ecore_exe_pipe_write_close(Ecore_Exe *exe);
|
||||
EAPI void *ecore_exe_free(Ecore_Exe *exe);
|
||||
EAPI pid_t ecore_exe_pid_get(Ecore_Exe *exe);
|
||||
EAPI void ecore_exe_tag_set(Ecore_Exe *exe, const char *tag);
|
||||
|
|
|
@ -71,6 +71,10 @@ int _ecore_exe_check_errno(int result, char *file, int line)
|
|||
* EMFILE Too many file descriptors used by process.
|
||||
* ENOLCK Problem getting a lock.
|
||||
* EPERM Not allowed to do that.
|
||||
* fsync
|
||||
* EBADF This is not an fd that is open for writing.
|
||||
* EINVAL, EROFS This is not an fd that can be fsynced.
|
||||
* EIO I/O error.
|
||||
*
|
||||
* How to use it -
|
||||
* int ok = 0;
|
||||
|
@ -88,7 +92,7 @@ int _ecore_exe_check_errno(int result, char *file, int line)
|
|||
* // Something failed, cleanup.
|
||||
* }
|
||||
*/
|
||||
switch (result)
|
||||
switch (saved_errno)
|
||||
{
|
||||
case EACCES :
|
||||
case EAGAIN :
|
||||
|
@ -118,6 +122,7 @@ int _ecore_exe_check_errno(int result, char *file, int line)
|
|||
case EFAULT :
|
||||
case EBADF :
|
||||
case EINVAL :
|
||||
case EROFS :
|
||||
case EISDIR :
|
||||
case EDEADLK :
|
||||
case EPERM :
|
||||
|
@ -137,9 +142,9 @@ int _ecore_exe_check_errno(int result, char *file, int line)
|
|||
fprintf(stderr,
|
||||
"*** NAUGHTY PROGRAMMER!!!\n"
|
||||
"*** SPANK SPANK SPANK!!!\n"
|
||||
"*** Unsupported errno code, please add this one.\n"
|
||||
"*** Now go fix your code in %s @%u. Tut tut tut!\n"
|
||||
"\n", __FILE__, __LINE__);
|
||||
"*** Unsupported errno code %d, please add this one.\n"
|
||||
"*** Now go fix your code in %s @%u, from %s @%u. Tut tut tut!\n"
|
||||
"\n", saved_errno, __FILE__, __LINE__, file, line);
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -193,6 +198,7 @@ ecore_exe_run(const char *exe_cmd, const void *data)
|
|||
ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
|
||||
exe->pid = pid;
|
||||
exe->data = (void *)data;
|
||||
exe->cmd = strdup(exe_cmd);
|
||||
exes = _ecore_list2_append(exes, exe);
|
||||
return exe;
|
||||
}
|
||||
|
@ -389,6 +395,8 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
{ /* Something went wrong, so pull down everything. */
|
||||
IF_FN_DEL(_ecore_exe_free, exe);
|
||||
}
|
||||
else
|
||||
printf("Running as %d for %s.\n", exe->pid, exe->cmd);
|
||||
|
||||
errno = n;
|
||||
return exe;
|
||||
|
@ -425,6 +433,25 @@ ecore_exe_pipe_write(Ecore_Exe *exe, void *data, int size)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stdin pipe of the given child process will close when the write buffer is empty.
|
||||
*
|
||||
* @param exe The child process to write to
|
||||
* @ingroup Ecore_Exe_Basic_Group
|
||||
*/
|
||||
void
|
||||
ecore_exe_pipe_write_close(Ecore_Exe *exe)
|
||||
{
|
||||
if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
|
||||
{
|
||||
ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
|
||||
"ecore_exe_pipe_write_close");
|
||||
return;
|
||||
}
|
||||
exe->close_write = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the string tag for the given process handle
|
||||
*
|
||||
|
@ -782,6 +809,7 @@ _ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
|||
unsigned char *inbuf;
|
||||
int inbuf_num;
|
||||
|
||||
//printf("Reading data for %s\n", exe->cmd);
|
||||
/* Get any left over data from last time. */
|
||||
inbuf = exe->read_data_buf;
|
||||
inbuf_num = exe->read_data_size;
|
||||
|
@ -890,14 +918,17 @@ _ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
|||
}
|
||||
if (lost_exe)
|
||||
{
|
||||
if (exe->exit_event)
|
||||
{ /* There is a pending exit event to send, so send it. */
|
||||
_ecore_event_add(ECORE_EVENT_EXE_EXIT, exe->exit_event,
|
||||
_ecore_event_exe_exit_free, NULL);
|
||||
exe->exit_event = NULL; /* Just being paranoid. */
|
||||
}
|
||||
else
|
||||
ecore_exe_terminate(exe); /* FIXME: give this some deep thought later. */
|
||||
if (exe->read_data_size)
|
||||
printf("Theer are %d bytes left unsent from the dead exe %s.\n", exe->read_data_size, exe->cmd);
|
||||
// if (exe->exit_event)
|
||||
// { /* There is a pending exit event to send, so send it. */
|
||||
//printf("Sending delayed exit event for %s.\n", exe->cmd);
|
||||
// _ecore_event_add(ECORE_EVENT_EXE_EXIT, exe->exit_event,
|
||||
// _ecore_event_exe_exit_free, NULL);
|
||||
// exe->exit_event = NULL; /* Just being paranoid. */
|
||||
// }
|
||||
// else
|
||||
// ecore_exe_terminate(exe); /* FIXME: give this some deep thought later. */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -916,6 +947,22 @@ _ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler)
|
|||
if ((exe->write_fd_handler) && (ecore_main_fd_handler_active_get(exe->write_fd_handler, ECORE_FD_WRITE)))
|
||||
_ecore_exe_flush(exe);
|
||||
|
||||
/* If we have sent all there is to send, and we need to close the pipe, then close it. */
|
||||
if ((exe->close_write == 1) && /*(!exe->write_data_buf) &&*/ (exe->write_data_size == exe->write_data_offset))
|
||||
{
|
||||
int ok = 0;
|
||||
int result;
|
||||
|
||||
printf("Closing stdin for %s\n", exe->cmd);
|
||||
// if (exe->child_fd_write) E_NO_ERRNO(result, fsync(exe->child_fd_write), ok);
|
||||
IF_FN_DEL(ecore_main_fd_handler_del, exe->write_fd_handler);
|
||||
if (exe->child_fd_write) E_NO_ERRNO(result, close(exe->child_fd_write), ok);
|
||||
exe->child_fd_write = 0;
|
||||
IF_FREE(exe->write_data_buf);
|
||||
exe->flags &= ~ECORE_EXE_PIPE_WRITE;
|
||||
exe->close_write = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,11 +191,7 @@ struct _Ecore_Exe
|
|||
int read_data_size; /* data read from child in bytes */
|
||||
int child_fd_write; /* fd to write TO to send data to the child */
|
||||
int child_fd_read; /* fd to read FROM when child has sent us (the parent) data */
|
||||
/* I thought a bit about wether or not their could be multiple exit events, then realised that since we
|
||||
* delete the exe on the first exit event, the answer is no. On the other hand, STOPing an exe may trigger
|
||||
* this, even though it has not truly exited. Probably should investigate this further.
|
||||
*/
|
||||
struct _Ecore_Event_Exe_Exit *exit_event; /* Process exit event */
|
||||
int close_write;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo);
|
|||
static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo);
|
||||
#endif
|
||||
|
||||
static int _ecore_signal_exe_exit_delay(void *data);
|
||||
|
||||
static volatile sig_atomic_t sig_count = 0;
|
||||
static volatile sig_atomic_t sigchld_count = 0;
|
||||
static volatile sig_atomic_t sigusr1_count = 0;
|
||||
|
@ -184,10 +186,37 @@ _ecore_signal_call(void)
|
|||
e->data = sigchld_info; /* FIXME: I'm not sure, but maybe we should clone this. I don't know if anybody uses it. */
|
||||
|
||||
if ((e->exe) && (e->exe->flags & ECORE_EXE_PIPE_READ))
|
||||
e->exe->exit_event = e; /* We want to report the Last Words of the exe, so delay this event. */
|
||||
{
|
||||
/* We want to report the Last Words of the exe, so delay this event.
|
||||
* There are three possibilities here -
|
||||
* 1 There are no Last Words.
|
||||
* 2 There are Last Words, they are not ready to be read.
|
||||
* 3 There are Last Words, they are ready to be read.
|
||||
*
|
||||
* For 1 we don't want to delay, for 3 we want to delay.
|
||||
* 2 is the problem. If we check for data now and there
|
||||
* is none, then there is no way to differentiate 1 and 2.
|
||||
* If we don't delay, we may loose data, but if we do delay,
|
||||
* there may not be data and the exit event never gets sent.
|
||||
*
|
||||
* Any way you look at it, there has to be some time passed
|
||||
* before the exit event gets sent. So the startegy here is
|
||||
* to setup a timer event that will send the exit event after
|
||||
* an arbitrary, but brief, time.
|
||||
*
|
||||
* This is probably paranoid, for the less paraniod, we could
|
||||
* check to see for Last Words, and only delay if there are any.
|
||||
* This has it's own set of problems.
|
||||
*/
|
||||
printf("Delaying exit event for %s.\n", e->exe->cmd);
|
||||
ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Sending exit event for %s.\n", e->exe->cmd);
|
||||
_ecore_event_add(ECORE_EVENT_EXE_EXIT, e,
|
||||
_ecore_event_exe_exit_free, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
sigchld_count--;
|
||||
|
@ -458,4 +487,19 @@ _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__)
|
|||
sig_count++;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
_ecore_signal_exe_exit_delay(void *data)
|
||||
{
|
||||
Ecore_Event_Exe_Exit *e;
|
||||
|
||||
e = data;
|
||||
if (e)
|
||||
{
|
||||
printf("Sending delayed exit event for %s.\n", e->exe->cmd);
|
||||
_ecore_event_add(ECORE_EVENT_EXE_EXIT, e,
|
||||
_ecore_event_exe_exit_free, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue