# HG changeset patch # User Christian Brabandt # Date 1457036105 -3600 # Node ID 764dba33605cc23dcd0e56a4e406ba5ce61427a7 # Parent 7aa65c2cc0f558b3ab326c6f2ef579103858138b commit https://github.com/vim/vim/commit/c25558bff4ed10d2642e6f5c016701641c494916 Author: Bram Moolenaar Date: Thu Mar 3 21:02:23 2016 +0100 patch 7.4.1484 Problem: Channel "err-io" value "out" is not supported. Solution: Connect stderr to stdout if wanted. diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5045,6 +5045,7 @@ mch_start_job(char **argv, job_T *job, j int fd_err[2]; /* for stderr */ # ifdef FEAT_CHANNEL channel_T *channel = NULL; + int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; #endif /* default is to fail */ @@ -5056,7 +5057,8 @@ mch_start_job(char **argv, job_T *job, j /* TODO: without the channel feature connect the child to /dev/null? */ # ifdef FEAT_CHANNEL /* Open pipes for stdin, stdout, stderr. */ - if ((pipe(fd_in) < 0) || (pipe(fd_out) < 0) ||(pipe(fd_err) < 0)) + if (pipe(fd_in) < 0 || pipe(fd_out) < 0 + || (!use_out_for_err && pipe(fd_err) < 0)) goto failed; channel = add_channel(); @@ -5093,17 +5095,26 @@ mch_start_job(char **argv, job_T *job, j ignored = dup(fd_in[0]); close(fd_in[0]); + /* set up stderr for the child */ + if (use_out_for_err) + { + close(2); + ignored = dup(fd_out[1]); + } + else + { + close(fd_err[0]); + close(2); + ignored = dup(fd_err[1]); + close(fd_err[1]); + } + /* set up stdout for the child */ close(fd_out[0]); close(1); ignored = dup(fd_out[1]); close(fd_out[1]); - /* set up stderr for the child */ - close(fd_err[0]); - close(2); - ignored = dup(fd_err[1]); - close(fd_err[1]); # endif /* See above for type of argv. */ @@ -5123,9 +5134,13 @@ mch_start_job(char **argv, job_T *job, j /* child stdin, stdout and stderr */ close(fd_in[0]); close(fd_out[1]); - close(fd_err[1]); # ifdef FEAT_CHANNEL - channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]); + if (!use_out_for_err) +# endif + close(fd_err[1]); +# ifdef FEAT_CHANNEL + channel_set_pipes(channel, fd_in[1], fd_out[0], + use_out_for_err ? INVALID_FD : fd_err[0]); channel_set_job(channel, job); channel_set_options(channel, options); # ifdef FEAT_GUI diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -5000,6 +5000,7 @@ mch_start_job(char *cmd, job_T *job, job HANDLE jo; # ifdef FEAT_CHANNEL channel_T *channel; + int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT; HANDLE ifd[2]; HANDLE ofd[2]; HANDLE efd[2]; @@ -5038,13 +5039,14 @@ mch_start_job(char *cmd, job_T *job, job || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0) || !CreatePipe(&ofd[0], &ofd[1], &saAttr, 0) || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0) - || !CreatePipe(&efd[0], &efd[1], &saAttr, 0) - || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)) + || (!use_out_for_err + && (!CreatePipe(&efd[0], &efd[1], &saAttr, 0) + || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))) goto failed; si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = ifd[0]; si.hStdOutput = ofd[1]; - si.hStdError = efd[1]; + si.hStdError = use_out_for_err ? ofd[1] : efd[1]; # endif if (!vim_create_process(cmd, TRUE, @@ -5075,10 +5077,12 @@ mch_start_job(char *cmd, job_T *job, job # ifdef FEAT_CHANNEL CloseHandle(ifd[0]); CloseHandle(ofd[1]); - CloseHandle(efd[1]); + if (!use_out_for_err) + CloseHandle(efd[1]); job->jv_channel = channel; - channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], (sock_T)efd[0]); + channel_set_pipes(channel, (sock_T)ifd[1], (sock_T)ofd[0], + use_out_for_err ? INVALID_FD : (sock_T)efd[0]); channel_set_job(channel, job); channel_set_options(channel, options); diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -339,10 +339,8 @@ func s:raw_one_time_callback(port) endfunc func Test_raw_one_time_callback() - call ch_logfile('channellog', 'w') call ch_log('Test_raw_one_time_callback()') call s:run_server('s:raw_one_time_callback') - call ch_logfile('') endfunc """"""""" @@ -420,6 +418,9 @@ func Test_nl_pipe() call ch_sendraw(handle, "echo something\n") call assert_equal("something", ch_readraw(handle)) + call ch_sendraw(handle, "echoerr wrong\n") + call assert_equal("wrong", ch_readraw(handle, {'part': 'err'})) + call ch_sendraw(handle, "double this\n") call assert_equal("this", ch_readraw(handle)) call assert_equal("AND this", ch_readraw(handle)) @@ -431,6 +432,25 @@ func Test_nl_pipe() endtry endfunc +func Test_nl_err_to_out_pipe() + if !has('job') + return + endif + call ch_log('Test_nl_err_to_out_pipe()') + let job = job_start(s:python . " test_channel_pipe.py", {'err-io': 'out'}) + call assert_equal("run", job_status(job)) + try + let handle = job_getchannel(job) + call ch_sendraw(handle, "echo something\n") + call assert_equal("something", ch_readraw(handle)) + + call ch_sendraw(handle, "echoerr wrong\n") + call assert_equal("wrong", ch_readraw(handle)) + finally + call job_stop(job) + endtry +endfunc + func Test_pipe_to_buffer() if !has('job') return diff --git a/src/testdir/test_channel_pipe.py b/src/testdir/test_channel_pipe.py --- a/src/testdir/test_channel_pipe.py +++ b/src/testdir/test_channel_pipe.py @@ -18,9 +18,12 @@ if __name__ == "__main__": print("Goodbye!") sys.stdout.flush() break - if typed.startswith("echo"): + if typed.startswith("echo "): print(typed[5:-1]) sys.stdout.flush() + if typed.startswith("echoerr"): + print(typed[8:-1], file=sys.stderr) + sys.stderr.flush() if typed.startswith("double"): print(typed[7:-1] + "\nAND " + typed[7:-1]) sys.stdout.flush() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -744,6 +744,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1484, +/**/ 1483, /**/ 1482,