@@ -28,13 +28,13 @@ function! denops#_internal#server#chan#connect(addr, options) abort
2828  endif 
2929  let  l: retry_threshold=  a: options
3030  let  l: retry_interval=  a: options
31-   let  l: previous_exception =  ' ' 
32-   for   l: i   in   range ( l: retry_threshold ) 
31+   let  l: i =  1 
32+   while   v: true 
3333    call  denops#_internal#echo#debug (printf (
3434          \  ' Connecting to channel `%s` [%d/%d]' 
3535          \  a: addr
36-           \  l: i  +   1 ,
37-           \  l: retry_threshold  +   1 ,
36+           \  l: i
37+           \  l: retry_threshold
3838          \) )
3939    try 
4040      call  s: connecta: addra: options
@@ -43,28 +43,45 @@ function! denops#_internal#server#chan#connect(addr, options) abort
4343      call  denops#_internal#echo#debug (printf (
4444            \  ' Failed to connect channel `%s` [%d/%d]: %s' 
4545            \  a: addr
46-             \  l: i  +   1 ,
47-             \  l: retry_threshold  +   1 ,
46+             \  l: i
47+             \  l: retry_threshold
4848            \  v: exception
4949            \) )
50-       let  l: previous_exception=  v: exception
50+       if  l: i>=  l: retry_threshold
51+         call  denops#_internal#echo#error (printf (
52+               \  ' Failed to connect channel `%s`: %s' 
53+               \  a: addr
54+               \  v: exception
55+               \) )
56+         return 
57+       endif 
5158    endtry 
5259    execute  printf (' sleep %dm' l: retry_interval
53-   endfor 
54-   call  denops#_internal#echo#error (printf (
55-         \  ' Failed to connect channel `%s`: %s' 
56-         \  a: addr
57-         \  l: previous_exception
58-         \) )
60+   endwhile 
5961endfunction 
6062
61- function !  denops#_internal#server#chan#close () abort 
63+ "  Args: 
64+ "    options: {
65+ "      timeout: number (default: 0)
66+ "    }
67+ function !  denops#_internal#server#chan#close (options ) abort 
6268  if  s: chanis # v: null
6369    throw  ' [denops] Channel does not exist yet' 
6470  endif 
71+   let  l: options=  extend ({
72+         \  ' timeout' 0 ,
73+         \} , a: options
6574  let  s: closed_on_purpose=  1 
66-   call  s: rpccloses: chan
67-   let  s: chan=  v: null
75+   if  l: optionstimeout  == # 0 
76+     return  s: force_closel: options
77+   endif 
78+   if  l: optionstimeout  >  0 
79+     let  s: force_close_delayer=  timer_start (
80+           \  l: optionstimeout ,
81+           \  { - > s: force_closel: options
82+           \) 
83+   endif 
84+   call  denops#_internal#server#chan#notify (' invoke' ' close' 
6885endfunction 
6986
7087function !  denops#_internal#server#chan#is_connected () abort 
@@ -91,36 +108,56 @@ endfunction
91108
92109function !  s: connectoptions ) abort 
93110  let  s: closed_on_purpose=  0 
94-   let  s: chan=  s: rpcconnecta: addr
95-         \  ' on_close' - > s: on_closea: options
96-         \} )
97111  let  s: addr=  a: addr
98112  let  s: options=  a: options
113+   let  s: chan=  s: rpcconnecta: addr
114+         \  ' on_close' - > s: on_close
115+         \} )
99116  call  denops#_internal#echo#debug (printf (' Channel connected (%s)' a: addr
100117  call  s: rpcnotifys: chan' void' 
101118endfunction 
102119
103- function !  s: on_closeoptions ) abort 
120+ function !  s: force_closeoptions ) abort 
121+   let  l: chan=  s: chan
122+   let  s: chan=  v: null
123+   call  s: clear_force_close_delayer
124+   call  denops#_internal#echo#warn (printf (
125+         \  ' Channel cannot close gracefully within %d millisec, force close (%s)' 
126+         \  a: optionstimeout ,
127+         \  s: addr
128+         \) )
129+   call  s: rpcclosel: chan
130+ endfunction 
131+ 
132+ function !  s: clear_force_close_delayerabort 
133+   if  exists (' s:force_close_delayer' 
134+     call  timer_stop (s: force_close_delayer
135+     unlet  s: force_close_delayer
136+   endif 
137+ endfunction 
138+ 
139+ function !  s: on_closeabort 
104140  let  s: chan=  v: null
141+   call  s: clear_force_close_delayer
105142  call  denops#_internal#echo#debug (printf (' Channel closed (%s)' s: addr
106143  doautocmd <nomodeline>  User  DenopsClosed
107-   if  ! a :||  s: closed_on_purpose||  s: exiting
144+   if  s: chan   isnot #  v: null   ||   ! s :||  s: closed_on_purpose||  s: exiting
108145    return 
109146  endif 
110147  "  Reconnect 
111-   if  s: reconnect_guarda: options 
148+   if  s: reconnect_guard
112149    return 
113150  endif 
114151  call  denops#_internal#echo#warn (' Channel closed. Reconnecting...' 
115152  call  timer_start (
116-         \  a :
153+         \  s :
117154        \  { - > denops#_internal#server#chan#connect (s: addrs: options
118155        \) 
119156endfunction 
120157
121- function !  s: reconnect_guardoptions ) abort 
122-   let  l: reconnect_threshold=  a :
123-   let  l: reconnect_interval=  a :
158+ function !  s: reconnect_guardabort 
159+   let  l: reconnect_threshold=  s :
160+   let  l: reconnect_interval=  s :
124161  let  s: reconnect_count=  get (s: ' reconnect_count' 0 ) +  1 
125162  if  s: reconnect_count>=  l: reconnect_threshold
126163    call  denops#_internal#echo#warn (printf (
0 commit comments