patch 8.2.3640: freeze when calling term_wait() in a close callback

Problem:    Freeze when calling term_wait() in a close callback.
Solution:   Set a "closing" flag to tell term_wait() to return. (closes #9152)
diff --git a/src/channel.c b/src/channel.c
index b46205e..7514d63 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -3156,6 +3156,10 @@
     {
 	ch_part_T	part;
 
+#ifdef FEAT_TERMINAL
+	// let the terminal know it is closing to avoid getting stuck
+	term_channel_closing(channel);
+#endif
 	// Invoke callbacks and flush buffers before the close callback.
 	if (channel->ch_close_cb.cb_name != NULL)
 	    ch_log(channel,
diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro
index 9304606..f5bd1a6 100644
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -20,6 +20,7 @@
 void term_win_entered(void);
 int terminal_loop(int blocking);
 int may_close_term_popup(void);
+void term_channel_closing(channel_T *ch);
 void term_channel_closed(channel_T *ch);
 void term_check_channel_closed_recently(void);
 int term_do_update_window(win_T *wp);
diff --git a/src/terminal.c b/src/terminal.c
index 24779d9..f6c283b 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -99,6 +99,7 @@
     int		tl_vterm_size_changed;
 
     int		tl_normal_mode; // TRUE: Terminal-Normal mode
+    int		tl_channel_closing;
     int		tl_channel_closed;
     int		tl_channel_recently_closed; // still need to handle tl_finish
 
@@ -3459,6 +3460,20 @@
 #endif
 
 /*
+ * Called when a channel is going to be closed, before invoking the close
+ * callback.
+ */
+    void
+term_channel_closing(channel_T *ch)
+{
+    term_T *term;
+
+    for (term = first_term; term != NULL; term = term->tl_next)
+	if (term->tl_job == ch->ch_job && !term->tl_channel_closed)
+	    term->tl_channel_closing = TRUE;
+}
+
+/*
  * Called when a channel has been closed.
  * If this was a channel for a terminal window then finish it up.
  */
@@ -6438,6 +6453,9 @@
 		// If the terminal is closed when the channel is closed the
 		// buffer disappears.
 		break;
+	    if (buf->b_term == NULL || buf->b_term->tl_channel_closing)
+		// came here from a close callback, only wait one time
+		break;
 	}
 
 	term_flush_messages();
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index 62dfbf1..8cdb42a 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -2058,5 +2058,22 @@
   bwipe!
 endfunc
 
+func Close_cb(ch, ctx)
+  call term_wait(a:ctx.bufnr)
+  let g:close_done = 'done'
+endfunc
+
+func Test_term_wait_in_close_cb()
+  let g:close_done = ''
+  let ctx = {}
+  let ctx.bufnr = term_start('echo "HELLO WORLD"',
+        \ {'close_cb': {ch -> Close_cb(ch, ctx)}})
+
+  call WaitForAssert({-> assert_equal("done", g:close_done)})
+
+  unlet g:close_done
+  bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 6162d87..a83ff61 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3640,
+/**/
     3639,
 /**/
     3638,