From 09e3c0ebaa5acee8dafbb7ecf4ebdf3aa2a9abad Mon Sep 17 00:00:00 2001
From: Lars Kanis <kanis@comcard.de>
Date: Mon, 13 Feb 2012 12:18:42 +0100
Subject: [PATCH] Fix invalid memory access in final GC call when using
 FXMenuCommand with acckey

Calling other classes while garbage collection is generally dangerous and useless.
---
 ext/fox16/FXRuby.cpp    |  6 +++---
 ext/fox16/markfuncs.cpp | 17 ++++++++++++-----
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/ext/fox16/FXRuby.cpp b/ext/fox16/FXRuby.cpp
index 8f5e7dd..faf67c6 100644
--- a/ext/fox16/FXRuby.cpp
+++ b/ext/fox16/FXRuby.cpp
@@ -1536,7 +1536,7 @@ FXwchar FXRbCallWCharMethod(const FXObject* recv, ID func){
 FXRbMenuCommand::~FXRbMenuCommand(){
   FXAccelTable *table;
   FXWindow *owner;
-  if(acckey){
+  if(acckey && !FXRbIsInGC(this)){
     owner=getShell()->getOwner();
     if(owner){
       table=owner->getAccelTable();
@@ -1552,7 +1552,7 @@ FXRbMenuCommand::~FXRbMenuCommand(){
 FXRbMenuCheck::~FXRbMenuCheck(){
   FXAccelTable *table;
   FXWindow *owner;
-  if(acckey){
+  if(acckey && !FXRbIsInGC(this)){
     owner=getShell()->getOwner();
     if(owner){
       table=owner->getAccelTable();
@@ -1568,7 +1568,7 @@ FXRbMenuCheck::~FXRbMenuCheck(){
 FXRbMenuRadio::~FXRbMenuRadio(){
   FXAccelTable *table;
   FXWindow *owner;
-  if(acckey){
+  if(acckey && !FXRbIsInGC(this)){
     owner=getShell()->getOwner();
     if(owner){
       table=owner->getAccelTable();
diff --git a/ext/fox16/markfuncs.cpp b/ext/fox16/markfuncs.cpp
index 87b75f6..040ea3b 100644
--- a/ext/fox16/markfuncs.cpp
+++ b/ext/fox16/markfuncs.cpp
@@ -53,9 +53,16 @@ void FXRbObject::markfunc(FXObject* obj){
   FXTRACE((100,"%s::markfunc(%p)\n",obj?obj->getClassName():"FXRbObject",obj));
   }
 
-static void FXRbSetInGCRecursive(FXWindow *window, bool enabled){
+static void FXRbSetInGCParentsRecursive(FXWindow *window, bool enabled){
   FXRbSetInGC( window, true );
-  if(window->getParent()) FXRbSetInGCRecursive( window->getParent(), enabled );
+  if(window->getParent()) FXRbSetInGCParentsRecursive( window->getParent(), enabled );
+  }
+
+static void FXRbSetInGCChildrenRecursive(FXWindow *window, bool enabled){
+  FXRbSetInGC( window, true );
+  for(FXWindow* child=window->getFirst(); child; child=child->getNext()){
+    FXRbSetInGCChildrenRecursive( child, enabled );
+    }
   }
 
 
@@ -78,9 +85,9 @@ void FXRbObject::freefunc(FXObject* self){
       // The parent window should also be scheduled to be free'd. In the other case,
       // the child window would have been marked as used.
       if(self->isMemberOf(FXMETACLASS(FXWindow))){
-        if(FXWindow *parent = dynamic_cast<FXWindow*>(self)->getParent()){
-          FXRbSetInGCRecursive( parent, true );
-          }
+        FXWindow *window = dynamic_cast<FXWindow*>(self);
+        FXRbSetInGCParentsRecursive( window, true );
+        FXRbSetInGCChildrenRecursive( window, true );
         }
       delete self;
       }
-- 
GitLab