2
0
Эх сурвалжийг харах

* fix crash in case of main thread exiting simultaneously with other threads (issue #11006)

git-svn-id: trunk@10492 -
micha 17 жил өмнө
parent
commit
ae8289f9f7
1 өөрчлөгдсөн 25 нэмэгдсэн , 15 устгасан
  1. 25 15
      rtl/inc/heap.inc

+ 25 - 15
rtl/inc/heap.inc

@@ -190,9 +190,9 @@ const
 {$endif}
 {$endif}
 
 
 var
 var
-  main_relo_freelists : pfreelists;
   orphaned_freelists : tfreelists;
   orphaned_freelists : tfreelists;
   heap_lock : trtlcriticalsection;
   heap_lock : trtlcriticalsection;
+  heap_lock_use : integer;
 threadvar
 threadvar
   freelists : tfreelists;
   freelists : tfreelists;
 
 
@@ -1392,6 +1392,12 @@ procedure InitHeapThread;
 var
 var
   loc_freelists: pfreelists;
   loc_freelists: pfreelists;
 begin
 begin
+  if heap_lock_use > 0 then
+  begin
+    entercriticalsection(heap_lock);
+    inc(heap_lock_use);
+    leavecriticalsection(heap_lock);
+  end;
   loc_freelists := @freelists;
   loc_freelists := @freelists;
   fillchar(loc_freelists^,sizeof(tfreelists),0);
   fillchar(loc_freelists^,sizeof(tfreelists),0);
 {$ifdef DUMP_MEM_USAGE}
 {$ifdef DUMP_MEM_USAGE}
@@ -1406,6 +1412,7 @@ var
 begin
 begin
   { we cannot initialize the locks here yet, thread support is
   { we cannot initialize the locks here yet, thread support is
     not loaded yet }
     not loaded yet }
+  heap_lock_use := 0;
   loc_freelists := @freelists;
   loc_freelists := @freelists;
   fillchar(loc_freelists^,sizeof(tfreelists),0);
   fillchar(loc_freelists^,sizeof(tfreelists),0);
   fillchar(orphaned_freelists,sizeof(orphaned_freelists),0);
   fillchar(orphaned_freelists,sizeof(orphaned_freelists),0);
@@ -1417,9 +1424,12 @@ var
 begin
 begin
   { this function should be called in main thread context }
   { this function should be called in main thread context }
   loc_freelists := @freelists;
   loc_freelists := @freelists;
-  main_relo_freelists := loc_freelists;
+  heap_lock_use := 1;
   initcriticalsection(heap_lock);
   initcriticalsection(heap_lock);
-  modify_freelists(loc_freelists, main_relo_freelists);
+  { loc_freelists still points to main thread's freelists, but they
+    have a reference to the global main freelists, fix them to point
+    to the main thread specific variable }
+  modify_freelists(loc_freelists, loc_freelists);
   if MemoryManager.RelocateHeap <> nil then
   if MemoryManager.RelocateHeap <> nil then
     MemoryManager.RelocateHeap();
     MemoryManager.RelocateHeap();
 end;
 end;
@@ -1428,12 +1438,13 @@ procedure FinalizeHeap;
 var
 var
   poc, poc_next: poschunk;
   poc, poc_next: poschunk;
   loc_freelists: pfreelists;
   loc_freelists: pfreelists;
+  last_thread: boolean;
 {$ifdef DUMP_MEM_USAGE}
 {$ifdef DUMP_MEM_USAGE}
   i : longint;
   i : longint;
 {$endif}
 {$endif}
 begin
 begin
   loc_freelists := @freelists;
   loc_freelists := @freelists;
-  if main_relo_freelists <> nil then
+  if heap_lock_use > 0 then
   begin
   begin
     entercriticalsection(heap_lock);
     entercriticalsection(heap_lock);
     finish_waitfixedlist(loc_freelists);
     finish_waitfixedlist(loc_freelists);
@@ -1453,22 +1464,21 @@ begin
   end;
   end;
   loc_freelists^.oslist := nil;
   loc_freelists^.oslist := nil;
   loc_freelists^.oscount := 0;
   loc_freelists^.oscount := 0;
-  if main_relo_freelists <> nil then
+  if heap_lock_use > 0 then
   begin
   begin
 {$endif HAS_SYSOSFREE}
 {$endif HAS_SYSOSFREE}
-    if main_relo_freelists <> loc_freelists then
+    poc := modify_freelists(loc_freelists, @orphaned_freelists);
+    if assigned(poc) then
     begin
     begin
-      poc := modify_freelists(loc_freelists, @orphaned_freelists);
-      if assigned(poc) then
-      begin
-        poc^.next_any := orphaned_freelists.oslist_all;
-        if assigned(orphaned_freelists.oslist_all) then
-          orphaned_freelists.oslist_all^.prev_any := poc;
-        orphaned_freelists.oslist_all := loc_freelists^.oslist_all;
-      end;
+      poc^.next_any := orphaned_freelists.oslist_all;
+      if assigned(orphaned_freelists.oslist_all) then
+        orphaned_freelists.oslist_all^.prev_any := poc;
+      orphaned_freelists.oslist_all := loc_freelists^.oslist_all;
     end;
     end;
+    dec(heap_lock_use);
+    last_thread := heap_lock_use = 0;
     leavecriticalsection(heap_lock);
     leavecriticalsection(heap_lock);
-    if main_relo_freelists = loc_freelists then
+    if last_thread then
       donecriticalsection(heap_lock);
       donecriticalsection(heap_lock);
   end;
   end;
 {$ifdef SHOW_MEM_USAGE}
 {$ifdef SHOW_MEM_USAGE}