From 84a83493c2bd9b01b3d90a2ebef49b0c698c0797 Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Fri, 17 Jan 2014 17:07:14 +0100
Subject: wx: wx could hang if wxe_server died (or had died) when inside a
 callback

The pid is not available via driver_caller(..) (see wxeCommand constr)
inside driver_monitor callback.
---
 lib/wx/c_src/wxe_driver.c |  4 ++--
 lib/wx/c_src/wxe_driver.h |  3 ++-
 lib/wx/c_src/wxe_impl.cpp | 30 +++++++++++++++++-------------
 3 files changed, 21 insertions(+), 16 deletions(-)

(limited to 'lib/wx')

diff --git a/lib/wx/c_src/wxe_driver.c b/lib/wx/c_src/wxe_driver.c
index 4d3aa577bf..ea52737fa2 100644
--- a/lib/wx/c_src/wxe_driver.c
+++ b/lib/wx/c_src/wxe_driver.c
@@ -1,7 +1,7 @@
 /*
  * %CopyrightBegin%
  *
- * Copyright Ericsson AB 2008-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2014. All Rights Reserved.
  *
  * The contents of this file are subject to the Erlang Public License,
  * Version 1.1, (the "License"); you may not use this file except in
@@ -195,7 +195,7 @@ void wxe_process_died(ErlDrvData handle, ErlDrvMonitor *monitor)
 {
    /* Callback is active for the dead process */
    wxe_data *sd = ((wxe_data *)handle);
-   push_command(WXE_CB_RETURN,NULL,0,sd);
+   push_command(WXE_CB_DIED,NULL,0,sd);
 
 /*    ErlDrvTermData pid; */
 /*    pid = driver_get_monitored_process(sd->port_handle, monitor);    */
diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h
index 0f0143bd4c..e35bbe2118 100644
--- a/lib/wx/c_src/wxe_driver.h
+++ b/lib/wx/c_src/wxe_driver.h
@@ -1,7 +1,7 @@
 /*
  * %CopyrightBegin%
  *
- * Copyright Ericsson AB 2008-2013. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2014. All Rights Reserved.
  *
  * The contents of this file are subject to the Erlang Public License,
  * Version 1.1, (the "License"); you may not use this file except in
@@ -89,6 +89,7 @@ extern char * erl_wx_privdir;
 #define WXE_BIN_INCR        11
 #define WXE_BIN_DECR        12
 #define WXE_INIT_OPENGL     13
+#define WXE_CB_DIED         14
 
 #define OPENGL_START        5000
 
diff --git a/lib/wx/c_src/wxe_impl.cpp b/lib/wx/c_src/wxe_impl.cpp
index 5c10881eda..1e8dfc0e58 100644
--- a/lib/wx/c_src/wxe_impl.cpp
+++ b/lib/wx/c_src/wxe_impl.cpp
@@ -66,7 +66,8 @@ int wxe_batch_caller = 0;  // inside batch if larger than 0
 
 void push_command(int op,char * buf,int len, wxe_data *sd)
 {
-  // fprintf(stderr, "Op %d %d\r\n", op, (int) driver_caller(sd->port_handle)),fflush(stderr);
+  /* fprintf(stderr, "Op %d %d [%ld] %d\r\n", op, (int) driver_caller(sd->port_handle),
+     wxe_batch->size(), wxe_batch_caller),fflush(stderr); */
   wxeCommand *Cmd = new wxeCommand(op, buf, len, sd);
   erl_drv_mutex_lock(wxe_batch_locker_m);
   wxe_batch->Append(Cmd);
@@ -189,17 +190,18 @@ void handle_event_callback(ErlDrvPort port, ErlDrvTermData process)
   WxeApp * app = (WxeApp *) wxTheApp;
   ErlDrvMonitor monitor;
   // Is thread safe if pdl have been incremented
-  driver_monitor_process(port, process, &monitor);
-  // Should we be able to handle commands when recursing? probably
-  erl_drv_mutex_lock(wxe_batch_locker_m);
-  //fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
-  app->recurse_level++;
-  app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
-  app->recurse_level--;
-  //fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
-  wxe_batch_caller = 0;
-  erl_drv_mutex_unlock(wxe_batch_locker_m);
-  driver_demonitor_process(port, &monitor);
+  if(driver_monitor_process(port, process, &monitor) == 0) {
+    // Should we be able to handle commands when recursing? probably
+    erl_drv_mutex_lock(wxe_batch_locker_m);
+    //fprintf(stderr, "\r\nCB EV Start %lu \r\n", process);fflush(stderr);
+    app->recurse_level++;
+    app->dispatch_cb(wxe_batch, wxe_batch_cb_saved, process);
+    app->recurse_level--;
+    //fprintf(stderr, "CB EV done %lu \r\n", process);fflush(stderr);
+    wxe_batch_caller = 0;
+    erl_drv_mutex_unlock(wxe_batch_locker_m);
+    driver_demonitor_process(port, &monitor);
+  }
 }
 
 void WxeApp::dispatch_cmds()
@@ -305,6 +307,7 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
 	  // fprintf(stderr, "  Ev %d %lu\r\n", event->op, event->caller);
 	  if(event->caller == process ||  // Callbacks from CB process only
 	     event->op == WXE_CB_START || // Event callback start change process
+	     event->op == WXE_CB_DIED ||  // Event callback process died
 	     // Allow connect_cb during CB i.e. msg from wxe_server.
 	     (memenv && event->caller == memenv->owner))
 	    {
@@ -317,7 +320,8 @@ void WxeApp::dispatch_cb(wxList * batch, wxList * temp, ErlDrvTermData process)
 		if(event->len > 0) {
 		  cb_buff = (char *) driver_alloc(event->len);
 		  memcpy(cb_buff, event->buffer, event->len);
-		}
+		}  // continue
+	      case WXE_CB_DIED:
 		callback_returned = 1;
 		return;
 	      case WXE_CB_START:
-- 
cgit v1.2.3