forked from aniani/vim
patch 8.0.1381: ch_readraw() waits for NL if channel mode is NL
Problem: ch_readraw() waits for NL if channel mode is NL. Solution: Pass a "raw" flag to channel_read_block(). (Yasuhiro Matsumoto)
This commit is contained in:
parent
05684310a5
commit
620ca2da37
@ -3313,11 +3313,12 @@ channel_read(channel_T *channel, ch_part_T part, char *func)
|
|||||||
/*
|
/*
|
||||||
* Read from RAW or NL "channel"/"part". Blocks until there is something to
|
* Read from RAW or NL "channel"/"part". Blocks until there is something to
|
||||||
* read or the timeout expires.
|
* read or the timeout expires.
|
||||||
|
* When "raw" is TRUE don't block waiting on a NL.
|
||||||
* Returns what was read in allocated memory.
|
* Returns what was read in allocated memory.
|
||||||
* Returns NULL in case of error or timeout.
|
* Returns NULL in case of error or timeout.
|
||||||
*/
|
*/
|
||||||
char_u *
|
static char_u *
|
||||||
channel_read_block(channel_T *channel, ch_part_T part, int timeout)
|
channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw)
|
||||||
{
|
{
|
||||||
char_u *buf;
|
char_u *buf;
|
||||||
char_u *msg;
|
char_u *msg;
|
||||||
@ -3340,6 +3341,10 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
|
|||||||
break;
|
break;
|
||||||
if (channel_collapse(channel, part, mode == MODE_NL) == OK)
|
if (channel_collapse(channel, part, mode == MODE_NL) == OK)
|
||||||
continue;
|
continue;
|
||||||
|
/* If not blocking or nothing more is coming then return what we
|
||||||
|
* have. */
|
||||||
|
if (raw || fd == INVALID_FD)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for up to the channel timeout. */
|
/* Wait for up to the channel timeout. */
|
||||||
@ -3366,11 +3371,16 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout)
|
|||||||
nl = channel_first_nl(node);
|
nl = channel_first_nl(node);
|
||||||
|
|
||||||
/* Convert NUL to NL, the internal representation. */
|
/* Convert NUL to NL, the internal representation. */
|
||||||
for (p = buf; p < nl && p < buf + node->rq_buflen; ++p)
|
for (p = buf; (nl == NULL || p < nl) && p < buf + node->rq_buflen; ++p)
|
||||||
if (*p == NUL)
|
if (*p == NUL)
|
||||||
*p = NL;
|
*p = NL;
|
||||||
|
|
||||||
if (nl + 1 == buf + node->rq_buflen)
|
if (nl == NULL)
|
||||||
|
{
|
||||||
|
/* must be a closed channel with missing NL */
|
||||||
|
msg = channel_get(channel, part);
|
||||||
|
}
|
||||||
|
else if (nl + 1 == buf + node->rq_buflen)
|
||||||
{
|
{
|
||||||
/* get the whole buffer */
|
/* get the whole buffer */
|
||||||
msg = channel_get(channel, part);
|
msg = channel_get(channel, part);
|
||||||
@ -3513,7 +3523,8 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw)
|
|||||||
timeout = opt.jo_timeout;
|
timeout = opt.jo_timeout;
|
||||||
|
|
||||||
if (raw || mode == MODE_RAW || mode == MODE_NL)
|
if (raw || mode == MODE_RAW || mode == MODE_NL)
|
||||||
rettv->vval.v_string = channel_read_block(channel, part, timeout);
|
rettv->vval.v_string = channel_read_block(channel, part,
|
||||||
|
timeout, raw);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (opt.jo_set & JO_ID)
|
if (opt.jo_set & JO_ID)
|
||||||
@ -3955,7 +3966,8 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval)
|
|||||||
timeout = opt.jo_timeout;
|
timeout = opt.jo_timeout;
|
||||||
else
|
else
|
||||||
timeout = channel_get_timeout(channel, part_read);
|
timeout = channel_get_timeout(channel, part_read);
|
||||||
rettv->vval.v_string = channel_read_block(channel, part_read, timeout);
|
rettv->vval.v_string = channel_read_block(channel, part_read,
|
||||||
|
timeout, TRUE);
|
||||||
}
|
}
|
||||||
free_job_options(&opt);
|
free_job_options(&opt);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ void channel_close(channel_T *channel, int invoke_close_cb);
|
|||||||
void channel_close_in(channel_T *channel);
|
void channel_close_in(channel_T *channel);
|
||||||
void channel_clear(channel_T *channel);
|
void channel_clear(channel_T *channel);
|
||||||
void channel_free_all(void);
|
void channel_free_all(void);
|
||||||
char_u *channel_read_block(channel_T *channel, ch_part_T part, int timeout);
|
|
||||||
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
|
void common_channel_read(typval_T *argvars, typval_T *rettv, int raw);
|
||||||
channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp);
|
channel_T *channel_fd2channel(sock_T fd, ch_part_T *partp);
|
||||||
void channel_handle_events(int only_keep_open);
|
void channel_handle_events(int only_keep_open);
|
||||||
|
@ -515,7 +515,7 @@ func Test_nl_pipe()
|
|||||||
call assert_equal("AND this", ch_readraw(handle))
|
call assert_equal("AND this", ch_readraw(handle))
|
||||||
|
|
||||||
call ch_sendraw(handle, "split this line\n")
|
call ch_sendraw(handle, "split this line\n")
|
||||||
call assert_equal("this linethis linethis line", ch_readraw(handle))
|
call assert_equal("this linethis linethis line", ch_read(handle))
|
||||||
|
|
||||||
let reply = ch_evalraw(handle, "quit\n")
|
let reply = ch_evalraw(handle, "quit\n")
|
||||||
call assert_equal("Goodbye!", reply)
|
call assert_equal("Goodbye!", reply)
|
||||||
@ -1266,6 +1266,31 @@ func Test_read_in_close_cb()
|
|||||||
endtry
|
endtry
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Use channel in NL mode but received text does not end in NL.
|
||||||
|
func Test_read_in_close_cb_incomplete()
|
||||||
|
if !has('job')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call ch_log('Test_read_in_close_cb_incomplete()')
|
||||||
|
|
||||||
|
let g:Ch_received = ''
|
||||||
|
func! CloseHandler(chan)
|
||||||
|
while ch_status(a:chan, {'part': 'out'}) == 'buffered'
|
||||||
|
let g:Ch_received .= ch_read(a:chan)
|
||||||
|
endwhile
|
||||||
|
endfunc
|
||||||
|
let job = job_start(s:python . " test_channel_pipe.py incomplete",
|
||||||
|
\ {'close_cb': 'CloseHandler'})
|
||||||
|
call assert_equal("run", job_status(job))
|
||||||
|
try
|
||||||
|
call WaitFor('g:Ch_received != ""')
|
||||||
|
call assert_equal('incomplete', g:Ch_received)
|
||||||
|
finally
|
||||||
|
call job_stop(job)
|
||||||
|
delfunc CloseHandler
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_out_cb_lambda()
|
func Test_out_cb_lambda()
|
||||||
if !has('job')
|
if !has('job')
|
||||||
return
|
return
|
||||||
|
@ -14,6 +14,10 @@ if __name__ == "__main__":
|
|||||||
if sys.argv[1].startswith("err"):
|
if sys.argv[1].startswith("err"):
|
||||||
print(sys.argv[1], file=sys.stderr)
|
print(sys.argv[1], file=sys.stderr)
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
elif sys.argv[1].startswith("incomplete"):
|
||||||
|
print(sys.argv[1], end='')
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
print(sys.argv[1])
|
print(sys.argv[1])
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
@ -772,7 +772,9 @@ static char *(features[]) =
|
|||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
/**/
|
/**/
|
||||||
1390,
|
1381,
|
||||||
|
/**/
|
||||||
|
1380,
|
||||||
/**/
|
/**/
|
||||||
1379,
|
1379,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user