Skip to content

Commit 4e221c9

Browse files
committed
patch 7.4.1398
Problem: The close-cb option is not implemented yet. Solution: Implemente close-cb. (Yasuhiro Matsumoto)
1 parent 0bb6108 commit 4e221c9

File tree

7 files changed

+116
-30
lines changed

7 files changed

+116
-30
lines changed

src/channel.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,11 @@ static char *e_cannot_connect = N_("E902: Cannot connect to port");
485485
* Returns NULL for failure.
486486
*/
487487
channel_T *
488-
channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
488+
channel_open(
489+
char *hostname,
490+
int port_in,
491+
int waittime,
492+
void (*nb_close_cb)(void))
489493
{
490494
int sd = -1;
491495
struct sockaddr_in server;
@@ -711,7 +715,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
711715
}
712716

713717
channel->CH_SOCK_FD = (sock_T)sd;
714-
channel->ch_close_cb = close_cb;
718+
channel->ch_nb_close_cb = nb_close_cb;
715719

716720
#ifdef FEAT_GUI
717721
channel_gui_register(channel);
@@ -790,6 +794,15 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
790794
else
791795
*cbp = NULL;
792796
}
797+
if (opt->jo_set & JO_CLOSE_CALLBACK)
798+
{
799+
cbp = &channel->ch_close_cb;
800+
vim_free(*cbp);
801+
if (opt->jo_close_cb != NULL && *opt->jo_close_cb != NUL)
802+
*cbp = vim_strsave(opt->jo_close_cb);
803+
else
804+
*cbp = NULL;
805+
}
793806
}
794807

795808
/*
@@ -1255,7 +1268,7 @@ may_invoke_callback(channel_T *channel, int part)
12551268
ch_mode_T ch_mode = channel->ch_part[part].ch_mode;
12561269
char_u *callback = NULL;
12571270

1258-
if (channel->ch_close_cb != NULL)
1271+
if (channel->ch_nb_close_cb != NULL)
12591272
/* this channel is handled elsewhere (netbeans) */
12601273
return FALSE;
12611274

@@ -1477,7 +1490,28 @@ channel_close(channel_T *channel)
14771490
}
14781491
#endif
14791492

1480-
channel->ch_close_cb = NULL;
1493+
if (channel->ch_close_cb != NULL)
1494+
{
1495+
typval_T argv[1];
1496+
typval_T rettv;
1497+
int dummy;
1498+
1499+
/* invoke the close callback; increment the refcount to avoid it
1500+
* being freed halfway */
1501+
argv[0].v_type = VAR_CHANNEL;
1502+
argv[0].vval.v_channel = channel;
1503+
++channel->ch_refcount;
1504+
call_func(channel->ch_close_cb, (int)STRLEN(channel->ch_close_cb),
1505+
&rettv, 1, argv, 0L, 0L, &dummy, TRUE, NULL);
1506+
clear_tv(&rettv);
1507+
--channel->ch_refcount;
1508+
1509+
/* the callback is only called once */
1510+
vim_free(channel->ch_close_cb);
1511+
channel->ch_close_cb = NULL;
1512+
}
1513+
1514+
channel->ch_nb_close_cb = NULL;
14811515
channel_clear(channel);
14821516
}
14831517

@@ -1539,6 +1573,8 @@ channel_clear(channel_T *channel)
15391573
#endif
15401574
vim_free(channel->ch_callback);
15411575
channel->ch_callback = NULL;
1576+
vim_free(channel->ch_close_cb);
1577+
channel->ch_close_cb = NULL;
15421578
}
15431579

15441580
#if defined(EXITFREE) || defined(PROTO)
@@ -1732,8 +1768,8 @@ channel_read(channel_T *channel, int part, char *func)
17321768
* keep stdin and stderr open? Probably not, assume the other side
17331769
* has died. */
17341770
channel_close(channel);
1735-
if (channel->ch_close_cb != NULL)
1736-
(*channel->ch_close_cb)();
1771+
if (channel->ch_nb_close_cb != NULL)
1772+
(*channel->ch_nb_close_cb)();
17371773

17381774
if (len < 0)
17391775
{

src/eval.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10067,6 +10067,18 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
1006710067
return FAIL;
1006810068
}
1006910069
}
10070+
else if (STRCMP(hi->hi_key, "close-cb") == 0)
10071+
{
10072+
if (!(supported & JO_CLOSE_CALLBACK))
10073+
break;
10074+
opt->jo_set |= JO_CLOSE_CALLBACK;
10075+
opt->jo_close_cb = get_callback(item);
10076+
if (opt->jo_close_cb == NULL)
10077+
{
10078+
EMSG2(_(e_invarg2), "close-cb");
10079+
return FAIL;
10080+
}
10081+
}
1007010082
else if (STRCMP(hi->hi_key, "waittime") == 0)
1007110083
{
1007210084
if (!(supported & JO_WAITTIME))
@@ -18924,7 +18936,7 @@ item_compare2(const void *s1, const void *s2)
1892418936

1892518937
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1892618938
res = call_func(sortinfo->item_compare_func,
18927-
(int)STRLEN(sortinfo->item_compare_func),
18939+
(int)STRLEN(sortinfo->item_compare_func),
1892818940
&rettv, 2, argv, 0L, 0L, &dummy, TRUE,
1892918941
sortinfo->item_compare_selfdict);
1893018942
clear_tv(&argv[0]);

src/proto/channel.pro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ channel_T *add_channel(void);
77
void channel_free(channel_T *channel);
88
void channel_gui_register(channel_T *channel);
99
void channel_gui_register_all(void);
10-
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void));
10+
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*nb_close_cb)(void));
1111
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
1212
void channel_set_job(channel_T *channel, job_T *job);
13-
void channel_set_options(channel_T *channel, jobopt_T *options);
13+
void channel_set_options(channel_T *channel, jobopt_T *opt);
1414
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, int id);
1515
char_u *channel_get(channel_T *channel, int part);
1616
int channel_collapse(channel_T *channel, int part);

src/structs.h

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,9 +1366,12 @@ struct channel_S {
13661366
* first error until the connection works
13671367
* again. */
13681368

1369-
void (*ch_close_cb)(void); /* callback for when channel is closed */
1369+
void (*ch_nb_close_cb)(void);
1370+
/* callback for Netbeans when channel is
1371+
* closed */
13701372

13711373
char_u *ch_callback; /* call when any msg is not handled */
1374+
char_u *ch_close_cb; /* call when channel is closed */
13721375

13731376
job_T *ch_job; /* Job that uses this channel; this does not
13741377
* count as a reference to avoid a circular
@@ -1377,25 +1380,27 @@ struct channel_S {
13771380
int ch_refcount; /* reference count */
13781381
};
13791382

1380-
#define JO_MODE 0x0001 /* channel mode */
1381-
#define JO_IN_MODE 0x0002 /* stdin mode */
1382-
#define JO_OUT_MODE 0x0004 /* stdout mode */
1383-
#define JO_ERR_MODE 0x0008 /* stderr mode */
1384-
#define JO_CALLBACK 0x0010 /* channel callback */
1385-
#define JO_OUT_CALLBACK 0x0020 /* stdout callback */
1386-
#define JO_ERR_CALLBACK 0x0040 /* stderr callback */
1387-
#define JO_WAITTIME 0x0080 /* only for ch_open() */
1388-
#define JO_TIMEOUT 0x0100 /* all timeouts */
1389-
#define JO_OUT_TIMEOUT 0x0200 /* stdout timeouts */
1390-
#define JO_ERR_TIMEOUT 0x0400 /* stderr timeouts */
1391-
#define JO_PART 0x0800 /* "part" */
1392-
#define JO_ID 0x1000 /* "id" */
1393-
#define JO_STOPONEXIT 0x2000 /* "stoponexit" */
1394-
#define JO_EXIT_CB 0x4000 /* "exit-cb" */
1395-
#define JO_ALL 0xffffff
1383+
#define JO_MODE 0x0001 /* channel mode */
1384+
#define JO_IN_MODE 0x0002 /* stdin mode */
1385+
#define JO_OUT_MODE 0x0004 /* stdout mode */
1386+
#define JO_ERR_MODE 0x0008 /* stderr mode */
1387+
#define JO_CALLBACK 0x0010 /* channel callback */
1388+
#define JO_OUT_CALLBACK 0x0020 /* stdout callback */
1389+
#define JO_ERR_CALLBACK 0x0040 /* stderr callback */
1390+
#define JO_CLOSE_CALLBACK 0x0080 /* close callback */
1391+
#define JO_WAITTIME 0x0100 /* only for ch_open() */
1392+
#define JO_TIMEOUT 0x0200 /* all timeouts */
1393+
#define JO_OUT_TIMEOUT 0x0400 /* stdout timeouts */
1394+
#define JO_ERR_TIMEOUT 0x0800 /* stderr timeouts */
1395+
#define JO_PART 0x1000 /* "part" */
1396+
#define JO_ID 0x2000 /* "id" */
1397+
#define JO_STOPONEXIT 0x4000 /* "stoponexit" */
1398+
#define JO_EXIT_CB 0x8000 /* "exit-cb" */
1399+
#define JO_ALL 0xffffff
13961400

13971401
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
1398-
#define JO_CB_ALL (JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK)
1402+
#define JO_CB_ALL \
1403+
(JO_CALLBACK + JO_OUT_CALLBACK + JO_ERR_CALLBACK + JO_CLOSE_CALLBACK)
13991404
#define JO_TIMEOUT_ALL (JO_TIMEOUT + JO_OUT_TIMEOUT + JO_ERR_TIMEOUT)
14001405

14011406
/*
@@ -1412,6 +1417,7 @@ typedef struct
14121417
char_u *jo_callback; /* not allocated! */
14131418
char_u *jo_out_cb; /* not allocated! */
14141419
char_u *jo_err_cb; /* not allocated! */
1420+
char_u *jo_close_cb; /* not allocated! */
14151421
int jo_waittime;
14161422
int jo_timeout;
14171423
int jo_out_timeout;

src/testdir/test_channel.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ def handle(self):
140140
print("sending: {}".format(cmd))
141141
self.request.sendall(cmd.encode('utf-8'))
142142
response = ""
143+
elif decoded[1] == 'close me':
144+
print("closing")
145+
self.request.close()
146+
response = ""
143147
elif decoded[1] == 'wait a bit':
144148
time.sleep(0.2)
145149
response = "waited"

src/testdir/test_channel.vim

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,9 @@ endfunc
471471

472472
"""""""""
473473

474-
let s:job_ret = 'not yet'
474+
let s:job_exit_ret = 'not yet'
475475
function MyExitCb(job, status)
476-
let s:job_ret = 'done'
476+
let s:job_exit_ret = 'done'
477477
endfunc
478478

479479
function s:test_exit_callback(port)
@@ -490,6 +490,32 @@ func Test_exit_callback()
490490

491491
" calling job_status() triggers the callback
492492
call job_status(s:exit_job)
493-
call assert_equal('done', s:job_ret)
493+
call assert_equal('done', s:job_exit_ret)
494494
endif
495495
endfunc
496+
497+
"""""""""
498+
499+
let s:ch_close_ret = 'alive'
500+
function MyCloseCb(ch)
501+
let s:ch_close_ret = 'closed'
502+
endfunc
503+
504+
function s:test_close_callback(port)
505+
let handle = ch_open('localhost:' . a:port, s:chopt)
506+
if ch_status(handle) == "fail"
507+
call assert_false(1, "Can't open channel")
508+
return
509+
endif
510+
call ch_setoptions(handle, {'close-cb': 'MyCloseCb'})
511+
512+
call assert_equal('', ch_sendexpr(handle, 'close me'))
513+
sleep 20m
514+
call assert_equal('closed', s:ch_close_ret)
515+
endfunc
516+
517+
func Test_close_callback()
518+
call ch_log('Test_close_callback()')
519+
call s:run_server('s:test_close_callback')
520+
endfunc
521+

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,8 @@ static char *(features[]) =
748748

749749
static int included_patches[] =
750750
{ /* Add new patch number below this line */
751+
/**/
752+
1398,
751753
/**/
752754
1397,
753755
/**/

0 commit comments

Comments
 (0)