Patch 7.4.1518
Problem: Channel with disconnected in/out/err is not supported.
Solution: Implement it for Unix.
Files: src/eval.c, src/os_unix.c, src/structs.h,
src/testdir/test_channel.vim, src/testdir/test_channel_pipe.py
*** ../vim-7.4.1517/src/eval.c 2016-03-08 17:08:38.558223138 +0100
--- src/eval.c 2016-03-08 18:18:34.206760505 +0100
***************
*** 10285,10291 ****
* Returns NULL if the handle is invalid.
*/
static channel_T *
! get_channel_arg(typval_T *tv)
{
channel_T *channel = NULL;
--- 10285,10291 ----
* Returns NULL if the handle is invalid.
*/
static channel_T *
! get_channel_arg(typval_T *tv, int check_open)
{
channel_T *channel = NULL;
***************
*** 10304,10310 ****
return NULL;
}
! if (channel == NULL || !channel_is_open(channel))
{
EMSG(_("E906: not an open channel"));
return NULL;
--- 10304,10310 ----
return NULL;
}
! if (check_open && (channel == NULL || !channel_is_open(channel)))
{
EMSG(_("E906: not an open channel"));
return NULL;
***************
*** 10318,10324 ****
static void
f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
{
! channel_T *channel = get_channel_arg(&argvars[0]);
if (channel != NULL)
{
--- 10318,10324 ----
static void
f_ch_close(typval_T *argvars, typval_T *rettv UNUSED)
{
! channel_T *channel = get_channel_arg(&argvars[0], TRUE);
if (channel != NULL)
{
***************
*** 10333,10339 ****
static void
f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
{
! channel_T *channel = get_channel_arg(&argvars[0]);
rettv->vval.v_number = -1;
if (channel != NULL)
--- 10333,10339 ----
static void
f_ch_getbufnr(typval_T *argvars, typval_T *rettv)
{
! channel_T *channel = get_channel_arg(&argvars[0], TRUE);
rettv->vval.v_number = -1;
if (channel != NULL)
***************
*** 10361,10367 ****
static void
f_ch_getjob(typval_T *argvars, typval_T *rettv)
{
! channel_T *channel = get_channel_arg(&argvars[0]);
if (channel != NULL)
{
--- 10361,10367 ----
static void
f_ch_getjob(typval_T *argvars, typval_T *rettv)
{
! channel_T *channel = get_channel_arg(&argvars[0], TRUE);
if (channel != NULL)
{
***************
*** 10383,10389 ****
channel_T *channel = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
! channel = get_channel_arg(&argvars[1]);
ch_log(channel, (char *)msg);
}
--- 10383,10389 ----
channel_T *channel = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
! channel = get_channel_arg(&argvars[1], TRUE);
ch_log(channel, (char *)msg);
}
***************
*** 10500,10506 ****
== FAIL)
return;
! channel = get_channel_arg(&argvars[0]);
if (channel != NULL)
{
if (opt.jo_set & JO_PART)
--- 10500,10506 ----
== FAIL)
return;
! channel = get_channel_arg(&argvars[0], TRUE);
if (channel != NULL)
{
if (opt.jo_set & JO_PART)
***************
*** 10570,10576 ****
channel_T *channel;
int part_send;
! channel = get_channel_arg(&argvars[0]);
if (channel == NULL)
return NULL;
part_send = channel_part_send(channel);
--- 10570,10576 ----
channel_T *channel;
int part_send;
! channel = get_channel_arg(&argvars[0], TRUE);
if (channel == NULL)
return NULL;
part_send = channel_part_send(channel);
***************
*** 10619,10625 ****
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
! channel = get_channel_arg(&argvars[0]);
if (channel == NULL)
return;
part_send = channel_part_send(channel);
--- 10619,10625 ----
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
! channel = get_channel_arg(&argvars[0], TRUE);
if (channel == NULL)
return;
part_send = channel_part_send(channel);
***************
*** 10736,10742 ****
channel_T *channel;
jobopt_T opt;
! channel = get_channel_arg(&argvars[0]);
if (channel == NULL)
return;
clear_job_options(&opt);
--- 10736,10742 ----
channel_T *channel;
jobopt_T opt;
! channel = get_channel_arg(&argvars[0], TRUE);
if (channel == NULL)
return;
clear_job_options(&opt);
***************
*** 10752,10768 ****
static void
f_ch_status(typval_T *argvars, typval_T *rettv)
{
/* return an empty string by default */
rettv->v_type = VAR_STRING;
! if (argvars[0].v_type != VAR_CHANNEL)
! {
! EMSG2(_(e_invarg2), get_tv_string(&argvars[0]));
! rettv->vval.v_string = NULL;
! }
! else
! rettv->vval.v_string = vim_strsave(
! (char_u *)channel_status(argvars[0].vval.v_channel));
}
#endif
--- 10752,10765 ----
static void
f_ch_status(typval_T *argvars, typval_T *rettv)
{
+ channel_T *channel;
+
/* return an empty string by default */
rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = NULL;
! channel = get_channel_arg(&argvars[0], FALSE);
! rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel));
}
#endif
*** ../vim-7.4.1517/src/os_unix.c 2016-03-08 15:37:36.734963213 +0100
--- src/os_unix.c 2016-03-08 18:00:02.826270515 +0100
***************
*** 5045,5055 ****
--- 5045,5061 ----
int fd_out[2]; /* for stdout */
int fd_err[2]; /* for stderr */
channel_T *channel = NULL;
+ int use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
+ int use_null_for_out = options->jo_io[PART_OUT] == JIO_NULL;
+ int use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL;
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
+ if (use_out_for_err && use_null_for_out)
+ use_null_for_err = TRUE;
+
/* default is to fail */
job->jv_status = JOB_FAILED;
fd_in[0] = -1;
***************
*** 5072,5078 ****
goto failed;
}
}
! else if (pipe(fd_in) < 0)
goto failed;
if (use_file_for_out)
--- 5078,5084 ----
goto failed;
}
}
! else if (!use_null_for_in && pipe(fd_in) < 0)
goto failed;
if (use_file_for_out)
***************
*** 5086,5092 ****
goto failed;
}
}
! else if (pipe(fd_out) < 0)
goto failed;
if (use_file_for_err)
--- 5092,5098 ----
goto failed;
}
}
! else if (!use_null_for_out && pipe(fd_out) < 0)
goto failed;
if (use_file_for_err)
***************
*** 5100,5111 ****
goto failed;
}
}
! else if (!use_out_for_err && pipe(fd_err) < 0)
goto failed;
! channel = add_channel();
! if (channel == NULL)
! goto failed;
# endif
pid = fork(); /* maybe we should use vfork() */
--- 5106,5120 ----
goto failed;
}
}
! else if (!use_out_for_err && !use_null_for_err && pipe(fd_err) < 0)
goto failed;
! if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
! {
! channel = add_channel();
! if (channel == NULL)
! goto failed;
! }
# endif
pid = fork(); /* maybe we should use vfork() */
***************
*** 5117,5122 ****
--- 5126,5135 ----
if (pid == 0)
{
+ # ifdef FEAT_CHANNEL
+ int null_fd = -1;
+ # endif
+
/* child */
reset_signals(); /* handle signals normally */
***************
*** 5131,5145 ****
/* TODO: re-enable this when pipes connect without a channel */
# ifdef FEAT_CHANNEL
/* set up stdin for the child */
! if (!use_file_for_in)
! close(fd_in[1]);
! close(0);
! 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]);
--- 5144,5174 ----
/* TODO: re-enable this when pipes connect without a channel */
# ifdef FEAT_CHANNEL
+ if (use_null_for_in || use_null_for_out || use_null_for_err)
+ null_fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
+
/* set up stdin for the child */
! if (use_null_for_in)
! {
! close(0);
! ignored = dup(null_fd);
! }
! else
! {
! if (!use_file_for_in)
! close(fd_in[1]);
! close(0);
! ignored = dup(fd_in[0]);
! close(fd_in[0]);
! }
/* set up stderr for the child */
! if (use_null_for_err)
! {
! close(2);
! ignored = dup(null_fd);
! }
! else if (use_out_for_err)
{
close(2);
ignored = dup(fd_out[1]);
***************
*** 5154,5164 ****
}
/* set up stdout for the child */
! if (!use_file_for_out)
! close(fd_out[0]);
! close(1);
! ignored = dup(fd_out[1]);
! close(fd_out[1]);
# endif
/* See above for type of argv. */
--- 5183,5203 ----
}
/* set up stdout for the child */
! if (use_null_for_out)
! {
! close(0);
! ignored = dup(null_fd);
! }
! else
! {
! if (!use_file_for_out)
! close(fd_out[0]);
! close(1);
! ignored = dup(fd_out[1]);
! close(fd_out[1]);
! }
! if (null_fd >= 0)
! close(null_fd);
# endif
/* See above for type of argv. */
***************
*** 5183,5199 ****
close(fd_out[1]);
if (!use_out_for_err && !use_file_for_err)
close(fd_err[1]);
! channel_set_pipes(channel,
! use_file_for_in ? INVALID_FD : fd_in[1],
! use_file_for_out ? INVALID_FD : fd_out[0],
! use_out_for_err || use_file_for_err
? INVALID_FD : fd_err[0]);
! channel_set_job(channel, job, options);
# ifdef FEAT_GUI
! channel_gui_register(channel);
# endif
# endif
return;
failed: ;
--- 5222,5244 ----
close(fd_out[1]);
if (!use_out_for_err && !use_file_for_err)
close(fd_err[1]);
! if (channel != NULL)
! {
! channel_set_pipes(channel,
! use_file_for_in || use_null_for_in
! ? INVALID_FD : fd_in[1],
! use_file_for_out || use_null_for_out
! ? INVALID_FD : fd_out[0],
! use_out_for_err || use_file_for_err || use_null_for_err
? INVALID_FD : fd_err[0]);
! channel_set_job(channel, job, options);
# ifdef FEAT_GUI
! channel_gui_register(channel);
# endif
+ }
# endif
+ /* success! */
return;
failed: ;
*** ../vim-7.4.1517/src/structs.h 2016-03-06 20:22:20.352165976 +0100
--- src/structs.h 2016-03-08 17:53:21.790418035 +0100
***************
*** 1417,1424 ****
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
typedef enum {
JIO_NULL,
- JIO_PIPE,
JIO_FILE,
JIO_BUFFER,
JIO_OUT
--- 1417,1424 ----
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
typedef enum {
+ JIO_PIPE, /* default */
JIO_NULL,
JIO_FILE,
JIO_BUFFER,
JIO_OUT
*** ../vim-7.4.1517/src/testdir/test_channel.vim 2016-03-08
16:06:51.048733393 +0100
--- src/testdir/test_channel.vim 2016-03-08 18:19:39.738081447 +0100
***************
*** 784,789 ****
--- 784,841 ----
endtry
endfunc
+ func Test_pipe_null()
+ if !has('job')
+ return
+ endif
+ " TODO: implement this for MS-Windows
+ if !has('unix')
+ return
+ endif
+ call ch_log('Test_pipe_null()')
+
+ " We cannot check that no I/O works, we only check that the job starts
+ " properly.
+ let job = job_start(s:python . " test_channel_pipe.py something",
+ \ {'in-io': 'null'})
+ call assert_equal("run", job_status(job))
+ try
+ call assert_equal('something', ch_read(job))
+ finally
+ call job_stop(job)
+ endtry
+
+ let job = job_start(s:python . " test_channel_pipe.py err-out",
+ \ {'out-io': 'null'})
+ call assert_equal("run", job_status(job))
+ try
+ call assert_equal('err-out', ch_read(job, {"part": "err"}))
+ finally
+ call job_stop(job)
+ endtry
+
+ let job = job_start(s:python . " test_channel_pipe.py something",
+ \ {'err-io': 'null'})
+ call assert_equal("run", job_status(job))
+ try
+ call assert_equal('something', ch_read(job))
+ finally
+ call job_stop(job)
+ endtry
+
+ let job = job_start(s:python . " test_channel_pipe.py something",
+ \ {'out-io': 'null', 'err-io': 'out'})
+ call assert_equal("run", job_status(job))
+ call job_stop(job)
+
+ let job = job_start(s:python . " test_channel_pipe.py something",
+ \ {'in-io': 'null', 'out-io': 'null', 'err-io': 'null'})
+ call assert_equal("run", job_status(job))
+ call assert_equal('channel fail', string(job_getchannel(job)))
+ call assert_equal('fail', ch_status(job))
+ call job_stop(job)
+ endfunc
+
""""""""""
let s:unletResponse = ''
*** ../vim-7.4.1517/src/testdir/test_channel_pipe.py 2016-03-08
15:37:36.734963213 +0100
--- src/testdir/test_channel_pipe.py 2016-03-08 17:31:19.792095528 +0100
***************
*** 10,16 ****
if __name__ == "__main__":
if len(sys.argv) > 1:
! print(sys.argv[1])
while True:
typed = sys.stdin.readline()
--- 10,21 ----
if __name__ == "__main__":
if len(sys.argv) > 1:
! if sys.argv[1].startswith("err"):
! print(sys.argv[1], file=sys.stderr)
! sys.stderr.flush()
! else:
! print(sys.argv[1])
! sys.stdout.flush()
while True:
typed = sys.stdin.readline()
*** ../vim-7.4.1517/src/version.c 2016-03-08 17:13:02.063486804 +0100
--- src/version.c 2016-03-08 17:26:56.018826202 +0100
***************
*** 745,746 ****
--- 745,748 ----
{ /* Add new patch number below this line */
+ /**/
+ 1518,
/**/
--
hundred-and-one symptoms of being an internet addict:
12. You turn off your modem and get this awful empty feeling, like you just
pulled the plug on a loved one.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.