[smuxi/stable] Frontend-GNOME-{IRC,XMPP}: fix non-safe thread access



commit 3f994d0e2cc6c128525a4d617b93f254574f89f3
Author: Mirco Bauer <meebey meebey net>
Date:   Sun Nov 19 12:10:58 2017 +0800

    Frontend-GNOME-{IRC,XMPP}: fix non-safe thread access
    
    ChatViewManager.ActiveChat is read from some GUI triggered operations in
    the CtcpMenu and InviteToMenu to execute commands handled by the protocol
    manager. Since the protocol manager is a remote object this RPC is performed in
    the thread-pool to not block the GUI thread as long as the RPC is not finished.
    At this point the access to ChatViewManager.ActiveChat is no longer safe,
    because the caller is now a non-GUI thread while ChatViewManager.get_ActiveChat()
    accesses GTK+ owned memory under the hood, to Gtk.TreeStore.GetValue().
    
    The awesome GTK# binding is reporting this unsafe access on stdout/err:
    
        ** (smuxi-frontend-gnome:11389): WARNING **: Gtk operations should be done on the main Thread
          at System.Environment.get_StackTrace () [0x00000] in <77c9551943624fd18301ba6f78a841e5>:0
          at Gtk.Application.AssertMainThread () [0x00000] in <e8d21baece374fadb4e2b3899720848c>:0
          at Gtk.TreeStore.GetValue (Gtk.TreeIter iter, System.Int32 column, GLib.Value& value) [0x00000] in 
<e8d21baece374fadb4e2b3899720848c>:0
          at Gtk.TreeStore.GetValue (Gtk.TreeIter iter, System.Int32 column) [0x00000] in 
<e8d21baece374fadb4e2b3899720848c>:0
          at Smuxi.Frontend.Gnome.ChatTreeView.get_CurrentChatView () [0x00023] in 
/build/smuxi-1.0.6/src/Frontend-GNOME/Views/ChatTreeView.cs:38
          at Smuxi.Frontend.Gnome.ChatViewManager.get_CurrentChatView () [0x00007] in 
/build/smuxi-1.0.6/src/Frontend-GNOME/ChatViewManager.cs:61
          at Smuxi.Frontend.Gnome.ChatViewManager.get_ActiveChat () [0x00002] in 
/build/smuxi-1.0.6/src/Frontend-GNOME/ChatViewManager.cs:55
          at Smuxi.Frontend.Gnome.CtcpMenu+<OnVersionItemActivated>c__AnonStorey1.<>m__0 (System.Object ) 
[0x00000] in <2e9f1637546f4ffd80909cc5eece1b95>:0
          at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x00000] 
in <77c9551943624fd18301ba6f78a841e5>:0
          at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext 
executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean 
preserveSyncCtx) [0x00000] in <77c9551943624fd18301ba6f78a841e5>:0
          at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, 
System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in 
<77c9551943624fd18301ba6f78a841e5>:0
          at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem 
() [0x00000] in <77c9551943624fd18301ba6f78a841e5>:0
          at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00000] in 
<77c9551943624fd18301ba6f78a841e5>:0
          at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in 
<77c9551943624fd18301ba6f78a841e5>:0

 src/Frontend-GNOME-IRC/CtcpMenu.cs      |   15 ++++++++++-----
 src/Frontend-GNOME-IRC/InviteToMenu.cs  |    3 ++-
 src/Frontend-GNOME-XMPP/InviteToMenu.cs |    3 ++-
 3 files changed, 14 insertions(+), 7 deletions(-)
---
diff --git a/src/Frontend-GNOME-IRC/CtcpMenu.cs b/src/Frontend-GNOME-IRC/CtcpMenu.cs
index c99c1e8..f790ba2 100644
--- a/src/Frontend-GNOME-IRC/CtcpMenu.cs
+++ b/src/Frontend-GNOME-IRC/CtcpMenu.cs
@@ -103,6 +103,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(sender, e);
 
+            var sourceChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (PersonModel target in Targets) {
                 var targetId = target.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -110,7 +111,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandPing(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                sourceChatModel,
                                 targetId
                             )
                         );
@@ -125,6 +126,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(sender, e);
 
+            var sourceChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (PersonModel target in Targets) {
                 var targetId = target.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -132,7 +134,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandVersion(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                sourceChatModel,
                                 targetId
                             )
                         );
@@ -147,6 +149,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(sender, e);
 
+            var sourceChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (PersonModel target in Targets) {
                 var targetId = target.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -154,7 +157,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandTime(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                sourceChatModel,
                                 targetId
                             )
                         );
@@ -169,6 +172,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(sender, e);
 
+            var sourceChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (PersonModel target in Targets) {
                 var targetId = target.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -176,7 +180,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandFinger(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                sourceChatModel,
                                 targetId
                             )
                         );
@@ -191,6 +195,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(sender, e);
 
+            var sourceChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (PersonModel target in Targets) {
                 var targetId = target.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -198,7 +203,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandCtcp(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                sourceChatModel,
                                 String.Format("{0} {1}", targetId, "USERINFO")
                             )
                         );
diff --git a/src/Frontend-GNOME-IRC/InviteToMenu.cs b/src/Frontend-GNOME-IRC/InviteToMenu.cs
index 15bfa31..808cf4c 100644
--- a/src/Frontend-GNOME-IRC/InviteToMenu.cs
+++ b/src/Frontend-GNOME-IRC/InviteToMenu.cs
@@ -100,6 +100,7 @@ namespace Smuxi.Frontend.Gnome
         {
             Trace.Call(chat);
 
+            var inviteFromChatModel = ChatViewManager.ActiveChat.ChatModel;
             foreach (var invitee in Invitees) {
                 var inviteeId = invitee.ID;
                 ThreadPool.QueueUserWorkItem(delegate {
@@ -107,7 +108,7 @@ namespace Smuxi.Frontend.Gnome
                         ProtocolManager.CommandInvite(
                             new CommandModel(
                                 Frontend.FrontendManager,
-                                ChatViewManager.ActiveChat.ChatModel,
+                                inviteFromChatModel,
                                 String.Format("{0} {1}", inviteeId, chat.ID)
                             )
                         );
diff --git a/src/Frontend-GNOME-XMPP/InviteToMenu.cs b/src/Frontend-GNOME-XMPP/InviteToMenu.cs
index 5f63086..9ee1299 100644
--- a/src/Frontend-GNOME-XMPP/InviteToMenu.cs
+++ b/src/Frontend-GNOME-XMPP/InviteToMenu.cs
@@ -90,13 +90,14 @@ namespace Smuxi.Frontend.Gnome
                     item.Image = new Gtk.Image(GroupChatView.IconPixbuf);
                     var chatid = chatView.ID;
                     item.Activated += delegate {
+                        var inviteFromChatModel = ChatViewManager.ActiveChat.ChatModel;
                         ThreadPool.QueueUserWorkItem(delegate {
                             try {
                                 for (int i = 0; i < Invitees.Count; i++) {
                                     ProtocolManager.CommandInvite(
                                         new CommandModel(
                                             Frontend.FrontendManager,
-                                            ChatViewManager.ActiveChat.ChatModel,
+                                            inviteFromChatModel,
                                             chatid + " " + Invitees[i].ID
                                         )
                                      );


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]