Skip to content

Commit bf6c580

Browse files
authored
Add test case to sgen-bridge-pathologies and add an assert to catch the original bug
1 parent 6ce5493 commit bf6c580

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/mono/mono/metadata/sgen-tarjan-bridge.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,11 @@ create_scc (ScanData *data)
794794

795795
// Maybe we should make sure we are not adding duplicates here. It is not really a problem
796796
// since we will get rid of duplicates before submitting the SCCs to the client in gather_xrefs
797-
if (color_data)
797+
if (color_data) {
798798
add_other_colors (color_data, &other->xrefs);
799+
} else {
800+
g_assert (dyn_array_ptr_size (&other->xrefs) == 0);
801+
}
799802
dyn_array_ptr_uninit (&other->xrefs);
800803

801804
if (other == data) {

src/mono/mono/tests/sgen-bridge-pathologies.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ public class NonBridge
1818
public object Link;
1919
}
2020

21+
public class NonBridge2 : NonBridge
22+
{
23+
public object Link2;
24+
}
25+
2126
class Driver {
2227
const int OBJ_COUNT = 200 * 1000;
2328
const int LINK_COUNT = 2;
@@ -207,6 +212,32 @@ static void Spider () {
207212
c.Links.Add (last_level);
208213
}
209214

215+
/*
216+
* Simulates a graph with two nested cycles that is produces by
217+
* the async state machine when `async Task M()` method gets its
218+
* continuation rooted by an Action held by RunnableImplementor
219+
* (ie. the task continuation is hooked through the SynchronizationContext
220+
* implentation and rooted only by Android bridge objects).
221+
*/
222+
static void NestedCycles ()
223+
{
224+
Bridge runnableImplementor = new Bridge ();
225+
Bridge byteArrayOutputStream = new Bridge ();
226+
NonBridge2 action = new NonBridge2 ();
227+
NonBridge displayClass = new NonBridge ();
228+
NonBridge2 asyncStateMachineBox = new NonBridge2 ();
229+
NonBridge2 asyncStreamWriter = new NonBridge2 ();
230+
231+
runnableImplementor.Links.Add(action);
232+
action.Link = displayClass;
233+
action.Link2 = asyncStateMachineBox;
234+
displayClass.Link = action;
235+
asyncStateMachineBox.Link = asyncStreamWriter;
236+
asyncStateMachineBox.Link2 = action;
237+
asyncStreamWriter.Link = byteArrayOutputStream;
238+
asyncStreamWriter.Link2 = asyncStateMachineBox;
239+
}
240+
210241
static void RunTest (ThreadStart setup)
211242
{
212243
var t = new Thread (setup);
@@ -231,6 +262,7 @@ static int Main ()
231262
RunTest (SetupDeadList);
232263
RunTest (SetupSelfLinks);
233264
RunTest (Spider);
265+
RunTest (NestedCycles);
234266

235267
for (int i = 0; i < 0; ++i) {
236268
GC.Collect ();

0 commit comments

Comments
 (0)