changeset 2639:73dd10c18ec4 v7.3.060

updated for version 7.3.060 Problem: Netbeans: crash when socket is disconnected unexpectedly. Solution: Don't cleanup when a read fails, put a message in the queue and disconnect later. (Xavier de Gaye)
author Bram Moolenaar <bram@vim.org>
date Tue, 16 Nov 2010 15:49:02 +0100
parents 75a89c7c204e
children 266f9d9f5109
files src/netbeans.c src/version.c
diffstat 2 files changed, 47 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -135,14 +135,12 @@ static int dosetvisible = FALSE;
 static int needupdate = 0;
 static int inAtomic = 0;
 
+/*
+ * Close the socket and remove the input handlers.
+ */
     static void
-netbeans_close(void)
+nb_close_socket(void)
 {
-    if (!NETBEANS_OPEN)
-	return;
-
-    netbeans_send_disconnect();
-
 #ifdef FEAT_GUI_X11
     if (inputHandler != (XtInputId)NULL)
     {
@@ -167,13 +165,27 @@ netbeans_close(void)
 # endif
 #endif
 
+    sock_close(nbsock);
+    nbsock = -1;
+}
+
+/*
+ * Close the connection and cleanup.
+ * May be called when nb_close_socket() was called earlier.
+ */
+    static void
+netbeans_close(void)
+{
+    if (NETBEANS_OPEN)
+    {
+	netbeans_send_disconnect();
+	nb_close_socket();
+    }
+
 #ifdef FEAT_BEVAL
     bevalServers &= ~BEVAL_NETBEANS;
 #endif
 
-    sock_close(nbsock);
-    nbsock = -1;
-
     needupdate = 0;
     inAtomic = 0;
     nb_free();
@@ -632,9 +644,6 @@ netbeans_parse_messages(void)
     char_u	*p;
     queue_T	*node;
 
-    if (!NETBEANS_OPEN)
-	return;
-
     while (head.next != NULL && head.next != &head)
     {
 	node = head.next;
@@ -720,6 +729,8 @@ messageFromNetbeans(gpointer clientData 
 }
 #endif
 
+#define DETACH_MSG "DETACH\n"
+
     void
 netbeans_read()
 {
@@ -780,22 +791,32 @@ netbeans_read()
 	    break;	/* did read everything that's available */
     }
 
+    /* Reading a socket disconnection (readlen == 0), or a socket error. */
     if (readlen <= 0)
     {
-	/* read error or didn't read anything */
-	netbeans_close();
-	nbdebug(("messageFromNetbeans: Error in read() from socket\n"));
+	/* Queue a "DETACH" netbeans message in the command queue in order to
+	 * terminate the netbeans session later. Do not end the session here
+	 * directly as we may be running in the context of a call to
+	 * netbeans_parse_messages():
+	 *	netbeans_parse_messages
+	 *	    -> autocmd triggered while processing the netbeans cmd
+	 *		-> ui_breakcheck
+	 *		    -> gui event loop or select loop
+	 *			-> netbeans_read()
+	 */
+	save((char_u *)DETACH_MSG, strlen(DETACH_MSG));
+	nb_close_socket();
+
 	if (len < 0)
 	{
 	    nbdebug(("read from Netbeans socket\n"));
 	    PERROR(_("read from Netbeans socket"));
 	}
-	return; /* don't try to parse it */
     }
 
 #if defined(NB_HAS_GUI) && defined(FEAT_GUI_GTK)
     if (NB_HAS_GUI && gtk_main_level() > 0)
-        gtk_main_quit();
+	gtk_main_quit();
 #endif
 }
 
@@ -1164,6 +1185,10 @@ nb_reply_nil(int cmdno)
 
     nbdebug(("REP %d: <none>\n", cmdno));
 
+    /* Avoid printing an annoying error message. */
+    if (!NETBEANS_OPEN)
+	return;
+
     sprintf(reply, "%d\n", cmdno);
     nb_send(reply, "nb_reply_nil");
 }
@@ -2753,11 +2778,11 @@ ex_nbstart(eap)
 {
 #ifdef FEAT_GUI
 # if !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)  \
-                && !defined(FEAT_GUI_W32)
+		&& !defined(FEAT_GUI_W32)
     if (gui.in_use)
     {
-        EMSG(_("E838: netbeans is not supported with this GUI"));
-        return;
+	EMSG(_("E838: netbeans is not supported with this GUI"));
+	return;
     }
 # endif
 #endif
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    60,
+/**/
     59,
 /**/
     58,