|
@@ -60,6 +60,7 @@ static bool_t action_stdout_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
void *associated_data, void *user_data);
|
|
|
static bool_t action_stderr_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
void *associated_data, void *user_data);
|
|
|
+static bool_t get_stream(ktpd_session_t *ktpd, int fd, bool_t is_stderr);
|
|
|
|
|
|
|
|
|
ktpd_session_t *ktpd_session_new(int sock, kscheme_t *scheme,
|
|
@@ -435,6 +436,11 @@ static bool_t wait_for_actions_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
if (!kexec_retcode(ktpd->exec, &retcode))
|
|
|
return BOOL_TRUE; // Continue
|
|
|
|
|
|
+ // Sometimes SIGCHILD signal can appear before all data were really read
|
|
|
+ // from process stdout buffer. So read the least data before closing
|
|
|
+ // file descriptors and send it to client.
|
|
|
+ get_stream(ktpd, kexec_stdout(ktpd->exec), BOOL_FALSE);
|
|
|
+ get_stream(ktpd, kexec_stderr(ktpd->exec), BOOL_TRUE);
|
|
|
faux_eloop_del_fd(eloop, kexec_stdout(ktpd->exec));
|
|
|
faux_eloop_del_fd(eloop, kexec_stderr(ktpd->exec));
|
|
|
|
|
@@ -1096,11 +1102,8 @@ int ktpd_session_fd(const ktpd_session_t *ktpd)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static bool_t get_stdout(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
- void *associated_data, void *user_data)
|
|
|
+static bool_t get_stream(ktpd_session_t *ktpd, int fd, bool_t is_stderr)
|
|
|
{
|
|
|
- faux_eloop_info_fd_t *info = (faux_eloop_info_fd_t *)associated_data;
|
|
|
- ktpd_session_t *ktpd = (ktpd_session_t *)user_data;
|
|
|
ssize_t r = -1;
|
|
|
faux_buf_t *faux_buf = NULL;
|
|
|
char *buf = NULL;
|
|
@@ -1112,7 +1115,10 @@ static bool_t get_stdout(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
if (!ktpd->exec)
|
|
|
return BOOL_TRUE;
|
|
|
|
|
|
- faux_buf = kexec_bufout(ktpd->exec);
|
|
|
+ if (is_stderr)
|
|
|
+ faux_buf = kexec_buferr(ktpd->exec);
|
|
|
+ else
|
|
|
+ faux_buf = kexec_bufout(ktpd->exec);
|
|
|
assert(faux_buf);
|
|
|
|
|
|
do {
|
|
@@ -1122,7 +1128,7 @@ static bool_t get_stdout(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
faux_buf_dwrite_lock_easy(faux_buf, &linear_buf);
|
|
|
// Non-blocked read. The fd became non-blocked while
|
|
|
// kexec_prepare().
|
|
|
- r = read(info->fd, linear_buf, linear_len);
|
|
|
+ r = read(fd, linear_buf, linear_len);
|
|
|
if (r > 0)
|
|
|
really_readed = r;
|
|
|
faux_buf_dwrite_unlock_easy(faux_buf, really_readed);
|
|
@@ -1135,18 +1141,14 @@ static bool_t get_stdout(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
buf = malloc(len);
|
|
|
faux_buf_read(faux_buf, buf, len);
|
|
|
|
|
|
- // Create KTP_STDOUT message to send to client
|
|
|
- ack = ktp_msg_preform(KTP_STDOUT, KTP_STATUS_NONE);
|
|
|
+ // Create KTP_STDOUT/KTP_STDERR message to send to client
|
|
|
+ ack = ktp_msg_preform(is_stderr ? KTP_STDERR : KTP_STDOUT, KTP_STATUS_NONE);
|
|
|
faux_msg_add_param(ack, KTP_PARAM_LINE, buf, len);
|
|
|
faux_msg_send_async(ack, ktpd->async);
|
|
|
faux_msg_free(ack);
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
- // Happy compiler
|
|
|
- eloop = eloop;
|
|
|
- type = type;
|
|
|
-
|
|
|
return BOOL_TRUE;
|
|
|
}
|
|
|
|
|
@@ -1156,6 +1158,7 @@ static bool_t action_stdout_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
void *associated_data, void *user_data)
|
|
|
{
|
|
|
faux_eloop_info_fd_t *info = (faux_eloop_info_fd_t *)associated_data;
|
|
|
+ ktpd_session_t *ktpd = (ktpd_session_t *)user_data;
|
|
|
|
|
|
// Interactive command use these function as callback not only for
|
|
|
// getting stdout but for writing stdin too. Because pseudo-terminal
|
|
@@ -1163,19 +1166,13 @@ static bool_t action_stdout_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
if (info->revents & POLLOUT)
|
|
|
push_stdin(eloop, type, associated_data, user_data);
|
|
|
|
|
|
- // Some errors or fd is closed so remove it from polling
|
|
|
if (info->revents & POLLIN)
|
|
|
- get_stdout(eloop, type, associated_data, user_data);
|
|
|
+ get_stream(ktpd, info->fd, BOOL_FALSE);
|
|
|
|
|
|
+ // Some errors or fd is closed so remove it from polling
|
|
|
// EOF || POLERR || POLLNVAL
|
|
|
- if (info->revents & (POLLHUP | POLLERR | POLLNVAL)) {
|
|
|
+ if (info->revents & (POLLHUP | POLLERR | POLLNVAL))
|
|
|
faux_eloop_del_fd(eloop, info->fd);
|
|
|
-// syslog(LOG_DEBUG, "Close fd %d (%x)", info->fd, info->revents);
|
|
|
- }
|
|
|
-
|
|
|
- // Happy compiler
|
|
|
- eloop = eloop;
|
|
|
- type = type;
|
|
|
|
|
|
return BOOL_TRUE;
|
|
|
}
|
|
@@ -1186,57 +1183,16 @@ static bool_t action_stderr_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
|
|
|
{
|
|
|
faux_eloop_info_fd_t *info = (faux_eloop_info_fd_t *)associated_data;
|
|
|
ktpd_session_t *ktpd = (ktpd_session_t *)user_data;
|
|
|
- ssize_t r = -1;
|
|
|
- faux_buf_t *faux_buf = NULL;
|
|
|
- char *buf = NULL;
|
|
|
- ssize_t len = 0;
|
|
|
- faux_msg_t *ack = NULL;
|
|
|
+
|
|
|
+ if (info->revents & POLLIN)
|
|
|
+ get_stream(ktpd, info->fd, BOOL_TRUE);
|
|
|
|
|
|
// Some errors or fd is closed so remove it from polling
|
|
|
- if (!(info->revents & POLLIN)) {
|
|
|
+ // EOF || POLERR || POLLNVAL
|
|
|
+ if (info->revents & (POLLHUP | POLLERR | POLLNVAL))
|
|
|
faux_eloop_del_fd(eloop, info->fd);
|
|
|
- return BOOL_TRUE;
|
|
|
- }
|
|
|
|
|
|
- if (!ktpd)
|
|
|
- return BOOL_TRUE;
|
|
|
- if (!ktpd->exec)
|
|
|
- return BOOL_TRUE;
|
|
|
-
|
|
|
- faux_buf = kexec_buferr(ktpd->exec);
|
|
|
- assert(faux_buf);
|
|
|
-
|
|
|
- do {
|
|
|
- void *linear_buf = NULL;
|
|
|
- ssize_t really_readed = 0;
|
|
|
- ssize_t linear_len =
|
|
|
- faux_buf_dwrite_lock_easy(faux_buf, &linear_buf);
|
|
|
- // Non-blocked read. The fd became non-blocked while
|
|
|
- // kexec_prepare().
|
|
|
- r = read(info->fd, linear_buf, linear_len);
|
|
|
- if (r > 0)
|
|
|
- really_readed = r;
|
|
|
- faux_buf_dwrite_unlock_easy(faux_buf, really_readed);
|
|
|
- } while (r > 0);
|
|
|
-
|
|
|
- len = faux_buf_len(faux_buf);
|
|
|
- if (0 == len)
|
|
|
- return BOOL_TRUE;
|
|
|
-
|
|
|
- buf = malloc(len);
|
|
|
- faux_buf_read(faux_buf, buf, len);
|
|
|
-
|
|
|
- // Create KTP_STDERR message to send to client
|
|
|
- ack = ktp_msg_preform(KTP_STDERR, KTP_STATUS_NONE);
|
|
|
- faux_msg_add_param(ack, KTP_PARAM_LINE, buf, len);
|
|
|
- faux_msg_send_async(ack, ktpd->async);
|
|
|
- faux_msg_free(ack);
|
|
|
-
|
|
|
- free(buf);
|
|
|
-
|
|
|
- // Happy compiler
|
|
|
- eloop = eloop;
|
|
|
- type = type;
|
|
|
+ type = type; // Happy compiler
|
|
|
|
|
|
return BOOL_TRUE;
|
|
|
}
|