exore_exe: fix from @raster

This commit is contained in:
Andrii Kroitor 2016-12-02 12:01:41 +02:00
parent 874071ca42
commit c505b754ce
2 changed files with 337 additions and 351 deletions

View File

@ -80,30 +80,27 @@ struct _Ecore_Exe_Data
Ecore_Win32_Handler *h_close; Ecore_Win32_Handler *h_close;
Ecore_Exe_Win32_Signal sig; Ecore_Exe_Win32_Signal sig;
struct Ecore_Thread *th;
{
struct {
HANDLE child_pipe; HANDLE child_pipe;
HANDLE thread;
void *data_buf; void *data_buf;
DWORD data_size; int data_size;
} pipe_read; } pipe_read;
struct struct {
{ HANDLE child_pipe;
void *data_buf;
int data_size;
} pipe_error;
struct {
HANDLE child_pipe; HANDLE child_pipe;
HANDLE child_pipe_x; HANDLE child_pipe_x;
void *data_buf; void *data_buf;
int data_size; int data_size;
} pipe_write; } pipe_write;
struct
{
HANDLE child_pipe;
HANDLE thread;
void *data_buf;
DWORD data_size;
} pipe_error;
Eina_Bool close_threads : 1; Eina_Bool close_threads : 1;
Eina_Bool is_suspended : 1; Eina_Bool is_suspended : 1;
#else #else

View File

@ -40,27 +40,11 @@ static void
_ecore_exe_threads_terminate(Ecore_Exe *obj) _ecore_exe_threads_terminate(Ecore_Exe *obj)
{ {
Ecore_Exe_Data *exe = efl_data_scope_get(obj, ECORE_EXE_CLASS); Ecore_Exe_Data *exe = efl_data_scope_get(obj, ECORE_EXE_CLASS);
HANDLE threads[2] = { NULL, NULL };
int i = 0;
if (!exe) return; if (!exe) return;
if (exe->pipe_read.thread) if (!exe->th) return;
{ ecore_thread_cancel(exe->th);
threads[i] = exe->pipe_read.thread; ecore_thread_wait(exe->th, 0.3);
i++;
}
if (exe->pipe_error.thread)
{
threads[i] = exe->pipe_error.thread;
i++;
}
if (i > 0)
{
exe->close_threads = 1;
WaitForMultipleObjects(i, threads, TRUE, INFINITE);
IF_FN_DEL(CloseHandle, exe->pipe_error.thread);
IF_FN_DEL(CloseHandle, exe->pipe_read.thread);
}
} }
static Eina_Bool static Eina_Bool
@ -81,10 +65,8 @@ _ecore_exe_close_cb(void *data,
/* FIXME : manage the STILL_ACTIVE returned error */ /* FIXME : manage the STILL_ACTIVE returned error */
if (!GetExitCodeProcess(exe->process, &exit_code)) if (!GetExitCodeProcess(exe->process, &exit_code))
{ {
char *msg; char *msg = evil_last_error_get();
DBG("%s", msg);
msg = evil_last_error_get();
printf("%s\n", msg);
free(msg); free(msg);
} }
@ -94,154 +76,182 @@ _ecore_exe_close_cb(void *data,
e->exe = obj; e->exe = obj;
exe->h_close = NULL; // It's going to get deleted in the next callback. exe->h_close = NULL; // It's going to get deleted in the next callback.
ecore_event_add(ECORE_EXE_EVENT_DEL, e, ecore_event_add(ECORE_EXE_EVENT_DEL, e, _ecore_exe_event_del_free, NULL);
_ecore_exe_event_del_free, NULL);
DBG("Exiting process %s with exit code %d\n", exe->cmd, e->exit_code); DBG("Exiting process %s with exit code %d\n", exe->cmd, e->exit_code);
return 0; return 0;
} }
static unsigned int __stdcall typedef struct
_ecore_exe_pipe_read_thread_cb(void *data)
{ {
char buf[64]; Ecore_Exe *obj;
Ecore_Exe *obj = data; HANDLE read_pipe;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, ECORE_EXE_CLASS); HANDLE error_pipe;
Ecore_Exe_Event_Data *event_data; Eina_Bool read : 1;
char *current_buf = NULL; Eina_Bool error : 1;
DWORD size; } Threaddata;
DWORD current_size = 0;
typedef struct
{
Ecore_Exe *obj;
unsigned char *buf;
int buf_size;
Eina_Bool read : 1;
Eina_Bool error : 1;
} Threadreply;
static void
_ecore_exe_win32_io_poll_thread(void *data, Ecore_Thread *th)
{
Threaddata *tdat = data;
Threadreply *trep;
Eina_Bool data_read, data_write;
char buf[4096];
DWORD size, current_size;
BOOL res; BOOL res;
if (!exe) return 0; while (EINA_TRUE)
while (1)
{ {
res = PeekNamedPipe(exe->pipe_read.child_pipe, data_read = EINA_FALSE;
buf, sizeof(buf) - 1, &size, &current_size, NULL); data_write = EINA_FALSE;
if (!res || (size == 0))
if (tdat->read)
{ {
if (exe->close_threads) res = PeekNamedPipe(tdat->read_pipe, buf, sizeof(buf),
break; &size, &current_size, NULL);
if (res && (size != 0))
Sleep(100); {
continue; trep = calloc(1, sizeof(Threadreply));
if (trep)
{
trep->obj = tdat->obj;
trep->buf = malloc(current_size);
if (trep->buf)
{
res = ReadFile(tdat->read_pipe, trep->buf,
current_size, &size, NULL);
if (!res || (size == 0))
{
free(trep->buf);
free(trep);
}
trep->buf_size = size;
trep->read = EINA_TRUE;
ecore_thread_feedback(th, trep);
data_read = EINA_TRUE;
}
}
}
} }
if (tdat->error)
current_buf = (char *)malloc(current_size);
if (!current_buf)
continue;
res = ReadFile(exe->pipe_read.child_pipe, current_buf, current_size, &size, NULL);
if (!res || (size == 0))
{ {
free(current_buf); res = PeekNamedPipe(tdat->error_pipe, buf, sizeof(buf),
current_buf = NULL; &size, &current_size, NULL);
continue; if (res && (size != 0))
{
trep = calloc(1, sizeof(Threadreply));
if (trep)
{
trep->obj = tdat->obj;
trep->buf = malloc(current_size);
if (trep->buf)
{
res = ReadFile(tdat->error_pipe, trep->buf,
current_size, &size, NULL);
if (!res || (size == 0))
{
free(trep->buf);
free(trep);
}
trep->buf_size = size;
trep->error = EINA_TRUE;
ecore_thread_feedback(th, trep);
//data_error = EINA_TRUE;
}
}
}
} }
if (ecore_thread_check(th)) break;
current_size = size; if (!(data_read || data_write)) Sleep(100);
else if (ecore_thread_check(th)) break;
if (!exe->pipe_read.data_buf)
{
exe->pipe_read.data_buf = current_buf;
exe->pipe_read.data_size = current_size;
}
else
{
exe->pipe_read.data_buf = realloc(exe->pipe_read.data_buf, exe->pipe_read.data_size + current_size);
memcpy((unsigned char *)exe->pipe_read.data_buf + exe->pipe_read.data_size, current_buf, current_size);
exe->pipe_read.data_size += current_size;
free(current_buf);
}
event_data = ecore_exe_event_data_get(obj, ECORE_EXE_PIPE_READ);
if (event_data)
{
ecore_event_add(ECORE_EXE_EVENT_DATA, event_data,
_ecore_exe_event_exe_data_free,
NULL);
efl_event_callback_call(obj, ECORE_EXE_EVENT_DATA_GET, event_data);
}
current_buf = NULL;
current_size = 0;
} }
free(tdat);
_endthreadex(0);
return 0;
} }
static unsigned int __stdcall static void
_ecore_exe_pipe_error_thread_cb(void *data) _ecore_exe_win32_io_poll_notify(void *data EINA_UNUSED,
Ecore_Thread *th EINA_UNUSED, void *msg)
{ {
char buf[64]; Threadreply *trep = msg;
Ecore_Exe *obj = data; Ecore_Exe *obj = trep->obj;
Ecore_Exe_Data *exe = efl_data_scope_get(obj, ECORE_EXE_CLASS); Ecore_Exe_Data *exe = efl_data_scope_get(obj, ECORE_EXE_CLASS);
Ecore_Exe_Event_Data *event_data; unsigned char *b;
char *current_buf = NULL;
DWORD size;
DWORD current_size = 0;
BOOL res;
if (!exe) return 0; if (exe)
while (1)
{ {
res = PeekNamedPipe(exe->pipe_error.child_pipe, Ecore_Exe_Event_Data *event_data;
buf, sizeof(buf) - 1, &size, &current_size, NULL);
if (!res || (size == 0)) if (trep->read)
{ {
if (exe->close_threads) if (!exe->pipe_read.data_buf)
break; {
exe->pipe_read.data_buf = trep->buf;
Sleep(100); exe->pipe_read.data_size = trep->buf_size;
continue; trep->buf = NULL;
}
else
{
b = realloc(exe->pipe_read.data_buf,
exe->pipe_read.data_size + trep->buf_size);
if (b)
{
memcpy(b + exe->pipe_read.data_size,
trep->buf, trep->buf_size);
exe->pipe_read.data_buf = b;
exe->pipe_read.data_size += trep->buf_size;
}
}
event_data = ecore_exe_event_data_get(obj, ECORE_EXE_PIPE_READ);
if (event_data)
{
ecore_event_add(ECORE_EXE_EVENT_DATA, event_data,
_ecore_exe_event_exe_data_free, NULL);
efl_event_callback_call(obj, ECORE_EXE_EVENT_DATA_GET,
event_data);
}
} }
else if (trep->error)
current_buf = (char *)malloc(current_size);
if (!current_buf)
continue;
res = ReadFile(exe->pipe_error.child_pipe, current_buf, current_size, &size, NULL);
if (!res || (size == 0))
{ {
free(current_buf); if (!exe->pipe_error.data_buf)
current_buf = NULL; {
continue; exe->pipe_error.data_buf = trep->buf;
exe->pipe_error.data_size = trep->buf_size;
trep->buf = NULL;
}
else
{
b = realloc(exe->pipe_error.data_buf,
exe->pipe_error.data_size + trep->buf_size);
if (b)
{
memcpy(b + exe->pipe_error.data_size,
trep->buf, trep->buf_size);
exe->pipe_error.data_buf = b;
exe->pipe_error.data_size += trep->buf_size;
}
}
event_data = ecore_exe_event_data_get(obj, ECORE_EXE_PIPE_ERROR);
if (event_data)
{
ecore_event_add(ECORE_EXE_EVENT_ERROR, event_data,
_ecore_exe_event_exe_data_free, NULL);
efl_event_callback_call(obj, ECORE_EXE_EVENT_DATA_ERROR,
event_data);
}
} }
current_size = size;
if (!exe->pipe_error.data_buf)
{
exe->pipe_error.data_buf = current_buf;
exe->pipe_error.data_size = current_size;
}
else
{
exe->pipe_error.data_buf = realloc(exe->pipe_error.data_buf, exe->pipe_error.data_size + current_size);
memcpy((unsigned char *)exe->pipe_error.data_buf + exe->pipe_error.data_size, current_buf, current_size);
exe->pipe_error.data_size += current_size;
free(current_buf);
}
event_data = ecore_exe_event_data_get(obj, ECORE_EXE_PIPE_ERROR);
if (event_data)
{
ecore_event_add(ECORE_EXE_EVENT_ERROR, event_data,
_ecore_exe_event_exe_data_free,
NULL);
efl_event_callback_call(obj, ECORE_EXE_EVENT_DATA_ERROR, event_data);
}
current_buf = NULL;
current_size = 0;
} }
free(trep->buf);
_endthreadex(0); free(trep);
return 0;
} }
static DWORD WINAPI static DWORD WINAPI
@ -269,54 +279,34 @@ _ecore_exe_enum_windows_procedure(HWND window,
if (CreateRemoteThread(exe->process, NULL, 0, if (CreateRemoteThread(exe->process, NULL, 0,
(LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL, (LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL,
0, NULL)) 0, NULL))
{ return EINA_FALSE;
printf ("remote thread\n");
return EINA_FALSE;
}
if ((exe->sig == ECORE_EXE_WIN32_SIGINT) || if ((exe->sig == ECORE_EXE_WIN32_SIGINT) ||
(exe->sig == ECORE_EXE_WIN32_SIGQUIT)) (exe->sig == ECORE_EXE_WIN32_SIGQUIT))
{ return EINA_FALSE;
printf ("int or quit\n");
return EINA_FALSE;
}
/* WM_CLOSE message */ /* WM_CLOSE message */
PostMessage(window, WM_CLOSE, 0, 0); PostMessage(window, WM_CLOSE, 0, 0);
if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0) if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
{ return EINA_FALSE;
printf ("CLOSE\n");
return EINA_FALSE;
}
/* WM_QUIT message */ /* WM_QUIT message */
PostMessage(window, WM_QUIT, 0, 0); PostMessage(window, WM_QUIT, 0, 0);
if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0) if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
{ return EINA_FALSE;
printf ("QUIT\n");
return EINA_FALSE;
}
/* Exit process */ /* Exit process */
if (CreateRemoteThread(exe->process, NULL, 0, if (CreateRemoteThread(exe->process, NULL, 0,
(LPTHREAD_START_ROUTINE)ExitProcess, NULL, (LPTHREAD_START_ROUTINE)ExitProcess, NULL,
0, NULL)) 0, NULL))
{ return EINA_FALSE;
printf ("remote thread 2\n");
return EINA_FALSE;
}
if (exe->sig == ECORE_EXE_WIN32_SIGTERM) if (exe->sig == ECORE_EXE_WIN32_SIGTERM)
{ return EINA_FALSE;
printf ("term\n");
return EINA_FALSE;
}
TerminateProcess(exe->process, 0); TerminateProcess(exe->process, 0);
return EINA_FALSE; return EINA_FALSE;
} }
return EINA_TRUE; return EINA_TRUE;
} }
@ -400,20 +390,16 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
flags = exe->flags; flags = exe->flags;
DBG("Creating process %s with flags %d", exe->cmd, flags); DBG("Creating process %s with flags %d", exe->cmd, flags);
if (!exe->cmd) goto error; if (!exe->cmd) goto error;
if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR)) 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. */ /* We need something to auto pipe. */
flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR; flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
if ((flags & ECORE_EXE_USE_SH)) if ((flags & ECORE_EXE_USE_SH)) use_sh = EINA_TRUE;
use_sh = EINA_TRUE; else use_sh = eina_str_has_extension(exe->cmd, ".bat");
else
use_sh = eina_str_has_extension(exe->cmd, ".bat");
if (use_sh) if (use_sh)
{ {
@ -435,45 +421,63 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
} }
/* stdout, stderr and stdin pipes */ /* stdout, stderr and stdin pipes */
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = EINA_TRUE; sa.bInheritHandle = EINA_TRUE;
sa.lpSecurityDescriptor = NULL; sa.lpSecurityDescriptor = NULL;
/* stdout pipe */ if ((exe->flags & ECORE_EXE_PIPE_READ) ||
if (exe->flags & ECORE_EXE_PIPE_READ) (exe->flags & ECORE_EXE_PIPE_ERROR))
{ {
if (!CreatePipe(&exe->pipe_read.child_pipe, &child_pipe_read, &sa, 0)) Threaddata *tdat;
goto error;
if (!SetHandleInformation(exe->pipe_read.child_pipe, HANDLE_FLAG_INHERIT, 0))
goto error;
exe->pipe_read.thread = (HANDLE)_beginthreadex(NULL, 0,
_ecore_exe_pipe_read_thread_cb,
obj, 0, NULL);
if (!exe->pipe_read.thread)
goto error;
}
/* stderr pipe */ tdat = calloc(1, sizeof(Threaddata));
if (exe->flags & ECORE_EXE_PIPE_ERROR) if (tdat)
{ {
if (!CreatePipe(&exe->pipe_error.child_pipe, &child_pipe_error, &sa, 0)) tdat->obj = obj;
goto error; /* stdout pipe */
if (!SetHandleInformation(exe->pipe_error.child_pipe, HANDLE_FLAG_INHERIT, 0)) if (exe->flags & ECORE_EXE_PIPE_READ)
goto error; {
exe->pipe_error.thread = (HANDLE)_beginthreadex(NULL, 0, if (!CreatePipe(&exe->pipe_read.child_pipe,
_ecore_exe_pipe_error_thread_cb, &child_pipe_read, &sa, 0))
obj, 0, NULL); goto error;
if (!exe->pipe_error.thread) if (!SetHandleInformation(exe->pipe_read.child_pipe,
goto error; HANDLE_FLAG_INHERIT, 0))
goto error;
tdat->read = EINA_TRUE;
tdat->read_pipe = exe->pipe_read.child_pipe;
}
/* stderr pipe */
if (exe->flags & ECORE_EXE_PIPE_ERROR)
{
if (!CreatePipe(&exe->pipe_error.child_pipe,
&child_pipe_error, &sa, 0))
goto error;
if (!SetHandleInformation(exe->pipe_error.child_pipe,
HANDLE_FLAG_INHERIT, 0))
goto error;
tdat->error = EINA_TRUE;
tdat->error_pipe = exe->pipe_error.child_pipe;
}
exe->th = ecore_thread_feedback_run
(_ecore_exe_win32_io_poll_thread,
_ecore_exe_win32_io_poll_notify,
NULL, NULL, tdat, EINA_TRUE);
if (!exe->th)
{
free(tdat);
goto error;
}
}
} }
/* stdin pipe */ /* stdin pipe */
if (exe->flags & ECORE_EXE_PIPE_WRITE) if (exe->flags & ECORE_EXE_PIPE_WRITE)
{ {
if (!CreatePipe(&exe->pipe_write.child_pipe, &exe->pipe_write.child_pipe_x, &sa, 0)) if (!CreatePipe(&exe->pipe_write.child_pipe,
&exe->pipe_write.child_pipe_x, &sa, 0))
goto error; goto error;
if (!SetHandleInformation(exe->pipe_write.child_pipe_x, HANDLE_FLAG_INHERIT, 0)) if (!SetHandleInformation(exe->pipe_write.child_pipe_x,
HANDLE_FLAG_INHERIT, 0))
goto error; goto error;
} }
@ -494,14 +498,14 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
{ {
char *msg; char *msg;
msg = evil_last_error_get(); msg = evil_last_error_get();
if (msg) if (msg)
{ {
WRN("Failed to create process %s: %s", exe_cmd_buf, msg); WRN("Failed to create process %s: %s", exe_cmd_buf, msg);
free(msg); free(msg);
} }
else else
WRN("Failed to create process %s: %ld", exe_cmd_buf, GetLastError()); WRN("Failed to create process %s: %ld", exe_cmd_buf, GetLastError());
goto error; goto error;
} }
@ -519,7 +523,6 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
/* FIXME: This does not work if the child is an EFL-based app */ /* FIXME: This does not work if the child is an EFL-based app */
/* if (WaitForInputIdle(pi.hProcess, INFINITE) == WAIT_FAILED) */ /* if (WaitForInputIdle(pi.hProcess, INFINITE) == WAIT_FAILED) */
/* goto error; */ /* goto error; */
exe->process = pi.hProcess; exe->process = pi.hProcess;
exe->process_thread = pi.hThread; exe->process_thread = pi.hThread;
exe->pid = pi.dwProcessId; exe->pid = pi.dwProcessId;
@ -527,8 +530,7 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
exe->h_close = ecore_main_win32_handler_add(exe->process, exe->h_close = ecore_main_win32_handler_add(exe->process,
_ecore_exe_close_cb, obj); _ecore_exe_close_cb, obj);
if (!exe->h_close) if (!exe->h_close) goto error;
goto error;
if (ResumeThread(exe->process_thread) == ((DWORD)-1)) if (ResumeThread(exe->process_thread) == ((DWORD)-1))
{ {
@ -538,14 +540,10 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
_ecore_exe_exes = eina_list_append(_ecore_exe_exes, obj); _ecore_exe_exes = eina_list_append(_ecore_exe_exes, obj);
e = (Ecore_Exe_Event_Add *)calloc(1, sizeof(Ecore_Exe_Event_Add)); e = calloc(1, sizeof(Ecore_Exe_Event_Add));
if (!e) goto error; if (!e) goto error;
e->exe = obj; e->exe = obj;
ecore_event_add(ECORE_EXE_EVENT_ADD, e, _ecore_exe_event_add_free, NULL);
ecore_event_add(ECORE_EXE_EVENT_ADD, e,
_ecore_exe_event_add_free, NULL);
return obj; return obj;
error: error:
@ -554,9 +552,9 @@ error:
Eina_Bool Eina_Bool
_impl_ecore_exe_send(Ecore_Exe *obj, _impl_ecore_exe_send(Ecore_Exe *obj,
Ecore_Exe_Data *exe, Ecore_Exe_Data *exe,
const void *data, const void *data,
int size) int size)
{ {
void *buf = NULL; void *buf = NULL;
DWORD num_exe; DWORD num_exe;
@ -570,7 +568,6 @@ _impl_ecore_exe_send(Ecore_Exe *obj,
exe->pipe_write.data_size += size; exe->pipe_write.data_size += size;
res = WriteFile(exe->pipe_write.child_pipe_x, buf, exe->pipe_write.data_size, &num_exe, NULL); res = WriteFile(exe->pipe_write.child_pipe_x, buf, exe->pipe_write.data_size, &num_exe, NULL);
printf(" ** res : %d\n", res);
if (!res || num_exe == 0) if (!res || num_exe == 0)
{ {
ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p", ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
@ -583,8 +580,8 @@ _impl_ecore_exe_send(Ecore_Exe *obj,
Ecore_Exe_Event_Data * Ecore_Exe_Event_Data *
_impl_ecore_exe_event_data_get(Ecore_Exe *obj, _impl_ecore_exe_event_data_get(Ecore_Exe *obj,
Ecore_Exe_Data *exe, Ecore_Exe_Data *exe,
Ecore_Exe_Flags flags) Ecore_Exe_Flags flags)
{ {
Ecore_Exe_Event_Data *e = NULL; Ecore_Exe_Event_Data *e = NULL;
unsigned char *inbuf; unsigned char *inbuf;
@ -593,103 +590,102 @@ _impl_ecore_exe_event_data_get(Ecore_Exe *obj,
/* Sort out what sort of event we are. */ /* Sort out what sort of event we are. */
if (flags & ECORE_EXE_PIPE_READ) if (flags & ECORE_EXE_PIPE_READ)
{ {
flags = ECORE_EXE_PIPE_READ; flags = ECORE_EXE_PIPE_READ;
if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED) if (exe->flags & ECORE_EXE_PIPE_READ_LINE_BUFFERED)
is_buffered = EINA_TRUE; is_buffered = EINA_TRUE;
} }
else else
{ {
flags = ECORE_EXE_PIPE_ERROR; flags = ECORE_EXE_PIPE_ERROR;
if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED) if (exe->flags & ECORE_EXE_PIPE_ERROR_LINE_BUFFERED)
is_buffered = EINA_TRUE; is_buffered = EINA_TRUE;
} }
/* Get the data. */ /* Get the data. */
if (flags & ECORE_EXE_PIPE_READ) if (flags & ECORE_EXE_PIPE_READ)
{ {
inbuf = exe->pipe_read.data_buf; inbuf = exe->pipe_read.data_buf;
inbuf_num = exe->pipe_read.data_size; inbuf_num = exe->pipe_read.data_size;
exe->pipe_read.data_buf = NULL; exe->pipe_read.data_buf = NULL;
exe->pipe_read.data_size = 0; exe->pipe_read.data_size = 0;
} }
else else
{ {
inbuf = exe->pipe_error.data_buf; inbuf = exe->pipe_error.data_buf;
inbuf_num = exe->pipe_error.data_size; inbuf_num = exe->pipe_error.data_size;
exe->pipe_error.data_buf = NULL; exe->pipe_error.data_buf = NULL;
exe->pipe_error.data_size = 0; exe->pipe_error.data_size = 0;
} }
e = calloc(1, sizeof(Ecore_Exe_Event_Data)); e = calloc(1, sizeof(Ecore_Exe_Event_Data));
if (e) if (e)
{ {
e->exe = obj; e->exe = obj;
e->data = inbuf; e->data = inbuf;
e->size = inbuf_num; e->size = inbuf_num;
if (is_buffered) /* Deal with line buffering. */ if (is_buffered) /* Deal with line buffering. */
{ {
char *c; char *c;
DWORD i; DWORD i;
DWORD max = 0; DWORD max = 0;
DWORD count = 0; DWORD count = 0;
DWORD last = 0; DWORD last = 0;
c = (char *)inbuf; c = (char *)inbuf;
for (i = 0; i < inbuf_num; i++) for (i = 0; i < inbuf_num; i++)
{ {
if (inbuf[i] == '\n') if (inbuf[i] == '\n')
{ {
int end; int end;
if (count >= max) if (count >= max)
{ {
max += 10; max += 10;
e->lines = realloc(e->lines, sizeof(Ecore_Exe_Event_Data_Line) * (max + 1)); e->lines = realloc
} (e->lines,
sizeof(Ecore_Exe_Event_Data_Line) * (max + 1));
if ((i >= 1) && (inbuf[i - 1] == '\r')) }
end = i - 1;
else
end = i;
inbuf[end] = '\0';
e->lines[count].line = c;
e->lines[count].size = end - last;
last = i + 1;
c = (char *)&inbuf[last];
count++;
}
}
if (i > last) /* Partial line left over, save it for next time. */
{
if (count != 0) e->size = last;
if (flags & ECORE_EXE_PIPE_READ)
{
exe->pipe_read.data_size = i - last;
exe->pipe_read.data_buf = malloc(exe->pipe_read.data_size);
memcpy(exe->pipe_read.data_buf, c, exe->pipe_read.data_size);
}
else
{
exe->pipe_error.data_size = i - last;
exe->pipe_error.data_buf = malloc(exe->pipe_error.data_size);
memcpy(exe->pipe_error.data_buf, c, exe->pipe_error.data_size);
}
}
if (count == 0) /* No lines to send, cancel the event. */
{
_ecore_exe_event_exe_data_free(NULL, e);
e = NULL;
}
else /* NULL terminate the array, so that people know where the end is. */
{
e->lines[count].line = NULL;
e->lines[count].size = 0;
}
}
}
if ((i >= 1) && (inbuf[i - 1] == '\r')) end = i - 1;
else end = i;
inbuf[end] = '\0';
e->lines[count].line = c;
e->lines[count].size = end - last;
last = i + 1;
c = (char *)&inbuf[last];
count++;
}
}
if (i > last) /* Partial line left over, save it for next time. */
{
if (count != 0) e->size = last;
if (flags & ECORE_EXE_PIPE_READ)
{
exe->pipe_read.data_size = i - last;
exe->pipe_read.data_buf = malloc(exe->pipe_read.data_size);
memcpy(exe->pipe_read.data_buf, c, exe->pipe_read.data_size);
}
else
{
exe->pipe_error.data_size = i - last;
exe->pipe_error.data_buf = malloc(exe->pipe_error.data_size);
memcpy(exe->pipe_error.data_buf, c, exe->pipe_error.data_size);
}
}
if (count == 0) /* No lines to send, cancel the event. */
{
_ecore_exe_event_exe_data_free(NULL, e);
e = NULL;
}
else /* NULL terminate the array, so that people know where the end is. */
{
e->lines[count].line = NULL;
e->lines[count].size = 0;
}
}
}
return e; return e;
} }
@ -701,8 +697,7 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe)
_ecore_exe_threads_terminate(obj); _ecore_exe_threads_terminate(obj);
data = exe->data; data = exe->data;
if (exe->pre_free_cb) if (exe->pre_free_cb) exe->pre_free_cb(data, obj);
exe->pre_free_cb(data, obj);
IF_FN_DEL(ecore_main_win32_handler_del, exe->h_close); IF_FN_DEL(ecore_main_win32_handler_del, exe->h_close);
@ -722,21 +717,15 @@ _impl_ecore_exe_efl_object_destructor(Eo *obj, Ecore_Exe_Data *exe)
void void
_impl_ecore_exe_pause(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe) _impl_ecore_exe_pause(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe)
{ {
if (exe->is_suspended) if (exe->is_suspended) return;
return; if (SuspendThread(exe->process_thread) != (DWORD)-1) exe->is_suspended = 1;
if (SuspendThread(exe->process_thread) != (DWORD)-1)
exe->is_suspended = 1;
} }
void void
_impl_ecore_exe_continue(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe) _impl_ecore_exe_continue(Ecore_Exe *obj EINA_UNUSED, Ecore_Exe_Data *exe)
{ {
if (!exe->is_suspended) if (!exe->is_suspended) return;
return; if (ResumeThread(exe->process_thread) != (DWORD)-1) exe->is_suspended = 0;
if (ResumeThread(exe->process_thread) != (DWORD)-1)
exe->is_suspended = 0;
} }
void void
@ -768,7 +757,7 @@ _impl_ecore_exe_terminate(Ecore_Exe *obj, Ecore_Exe_Data *exe)
CloseHandle(exe->process); CloseHandle(exe->process);
exe->process = NULL; exe->process = NULL;
exe->sig = ECORE_EXE_WIN32_SIGTERM; exe->sig = ECORE_EXE_WIN32_SIGTERM;
while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)obj)) ; while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)obj));
} }
void void
@ -779,31 +768,31 @@ _impl_ecore_exe_kill(Ecore_Exe *obj, Ecore_Exe_Data *exe)
CloseHandle(exe->process); CloseHandle(exe->process);
exe->process = NULL; exe->process = NULL;
exe->sig = ECORE_EXE_WIN32_SIGKILL; exe->sig = ECORE_EXE_WIN32_SIGKILL;
while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)obj)) ; while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)obj));
} }
void void
_impl_ecore_exe_auto_limits_set(Ecore_Exe *obj EINA_UNUSED, _impl_ecore_exe_auto_limits_set(Ecore_Exe *obj EINA_UNUSED,
Ecore_Exe_Data *exe EINA_UNUSED, Ecore_Exe_Data *exe EINA_UNUSED,
int start_bytes EINA_UNUSED, int start_bytes EINA_UNUSED,
int end_bytes EINA_UNUSED, int end_bytes EINA_UNUSED,
int start_lines EINA_UNUSED, int start_lines EINA_UNUSED,
int end_lines EINA_UNUSED) int end_lines EINA_UNUSED)
{ {
ERR("Not implemented on windows!"); ERR("Not implemented on windows!");
} }
void void
_impl_ecore_exe_signal(Ecore_Exe *obj EINA_UNUSED, _impl_ecore_exe_signal(Ecore_Exe *obj EINA_UNUSED,
Ecore_Exe_Data *exe EINA_UNUSED, Ecore_Exe_Data *exe EINA_UNUSED,
int num EINA_UNUSED) int num EINA_UNUSED)
{ {
ERR("Not implemented on windows!"); ERR("Not implemented on windows!");
} }
void void
_impl_ecore_exe_hup(Ecore_Exe *obj EINA_UNUSED, _impl_ecore_exe_hup(Ecore_Exe *obj EINA_UNUSED,
Ecore_Exe_Data *exe EINA_UNUSED) Ecore_Exe_Data *exe EINA_UNUSED)
{ {
ERR("Not implemented on windows!"); ERR("Not implemented on windows!");
} }