summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2014-11-22 19:33:48 +0100
committerSébastien Helleu <flashcode@flashtux.org>2014-11-22 19:33:48 +0100
commit3fac3b1bf9ba30ec09e503509c7ac3e25d29a14c (patch)
treef45ba102ac438e7b9a0578cac0efc53f80665f7f
parentcore: fix Lua detection on FreeBSD with cmake (diff)
downloadweechat-3fac3b1bf9ba30ec09e503509c7ac3e25d29a14c.tar.xz
weechat-3fac3b1bf9ba30ec09e503509c7ac3e25d29a14c.zip
api: fix truncated process output in hook_process() (closes #266)
-rw-r--r--ChangeLog.asciidoc1
-rw-r--r--src/core/wee-hook.c78
2 files changed, 78 insertions, 1 deletions
diff --git a/ChangeLog.asciidoc b/ChangeLog.asciidoc
index 73b05df47..d00318318 100644
--- a/ChangeLog.asciidoc
+++ b/ChangeLog.asciidoc
@@ -60,6 +60,7 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
* core: display time in bare display only if option
weechat.look.buffer_time_format is not an empty string
* core: fix translation of message displayed after /upgrade
+* api: fix truncated process output in hook_process() (closes #266)
* api: fix crash when reading config options with NULL value (closes #238)
* irc: use option irc.look.nick_mode_empty to display nick prefix in bar item
"input_prompt"
diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c
index c8234e83d..be43ccb5c 100644
--- a/src/core/wee-hook.c
+++ b/src/core/wee-hook.c
@@ -1708,7 +1708,7 @@ void
hook_process_child_read (struct t_hook *hook_process, int fd,
int index_buffer, struct t_hook **hook_fd)
{
- char buffer[4096];
+ char buffer[HOOK_PROCESS_BUFFER_SIZE / 8];
int num_read;
if (hook_process->deleted)
@@ -1764,6 +1764,80 @@ hook_process_child_read_stderr_cb (void *arg_hook_process, int fd)
}
/*
+ * Reads process output from child process until EOF
+ * (called when the child process has ended).
+ */
+
+void
+hook_process_child_read_until_eof (struct t_hook *hook_process)
+{
+ struct timeval tv_timeout;
+ fd_set read_fds, write_fds, except_fds;
+ int count, fd_stdout, fd_stderr, max_fd, ready;
+
+ fd_stdout = HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDOUT]);
+ fd_stderr = HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDERR]);
+
+ /*
+ * use a counter to prevent any infinite loop
+ * (if child's output is very very long...)
+ */
+ count = 0;
+ while (count < 1024)
+ {
+ FD_ZERO (&read_fds);
+ FD_ZERO (&write_fds);
+ FD_ZERO (&except_fds);
+
+ max_fd = -1;
+ if (HOOK_PROCESS(hook_process, hook_fd[HOOK_PROCESS_STDOUT])
+ && ((fcntl (fd_stdout, F_GETFD) != -1) || (errno != EBADF)))
+ {
+ FD_SET (fd_stdout, &read_fds);
+ if (fd_stdout > max_fd)
+ max_fd = fd_stdout;
+ }
+ if (HOOK_PROCESS(hook_process, hook_fd[HOOK_PROCESS_STDERR])
+ && ((fcntl (fd_stderr, F_GETFD) != -1) || (errno != EBADF)))
+ {
+ FD_SET (fd_stderr, &read_fds);
+ if (fd_stderr > max_fd)
+ max_fd = fd_stderr;
+ }
+
+ if (max_fd < 0)
+ break;
+
+ tv_timeout.tv_sec = 0;
+ tv_timeout.tv_usec = 0;
+
+ ready = select (max_fd + 1,
+ &read_fds, &write_fds, &except_fds,
+ &tv_timeout);
+
+ if (ready <= 0)
+ break;
+
+ if (FD_ISSET(fd_stdout, &read_fds))
+ {
+ (void) hook_process_child_read_stdout_cb (
+ hook_process,
+ HOOK_PROCESS(hook_process,
+ child_read[HOOK_PROCESS_STDOUT]));
+ }
+ if (FD_ISSET(fd_stderr, &read_fds))
+ {
+ (void) hook_process_child_read_stderr_cb (
+ hook_process,
+ HOOK_PROCESS(hook_process,
+ child_read[HOOK_PROCESS_STDERR]));
+ }
+
+ count++;
+ }
+}
+
+/*
* Checks if child process is still alive.
*/
@@ -1804,12 +1878,14 @@ hook_process_timer_cb (void *arg_hook_process, int remaining_calls)
{
/* child terminated normally */
rc = WEXITSTATUS(status);
+ hook_process_child_read_until_eof (hook_process);
hook_process_send_buffers (hook_process, rc);
unhook (hook_process);
}
else if (WIFSIGNALED(status))
{
/* child terminated by a signal */
+ hook_process_child_read_until_eof (hook_process);
hook_process_send_buffers (hook_process,
WEECHAT_HOOK_PROCESS_ERROR);
unhook (hook_process);