-
Notifications
You must be signed in to change notification settings - Fork 28.6k
[SPARK-26265][Core] Fix deadlock in BytesToBytesMap.MapIterator when locking both BytesToBytesMap.MapIterator and TaskMemoryManager #23272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,8 @@ | |
|
||
import org.apache.spark.SparkConf; | ||
import org.apache.spark.executor.ShuffleWriteMetrics; | ||
import org.apache.spark.memory.MemoryMode; | ||
import org.apache.spark.memory.TestMemoryConsumer; | ||
import org.apache.spark.memory.TaskMemoryManager; | ||
import org.apache.spark.memory.TestMemoryManager; | ||
import org.apache.spark.network.util.JavaUtils; | ||
|
@@ -667,4 +669,49 @@ public void testPeakMemoryUsed() { | |
} | ||
} | ||
|
||
@Test | ||
public void avoidDeadlock() throws InterruptedException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, @viirya . Since this test case reproduces There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried several ways to set a timeout logic, but don't work. The deadlock always hangs the test and timeout logic. |
||
memoryManager.limit(PAGE_SIZE_BYTES); | ||
MemoryMode mode = useOffHeapMemoryAllocator() ? MemoryMode.OFF_HEAP: MemoryMode.ON_HEAP; | ||
TestMemoryConsumer c1 = new TestMemoryConsumer(taskMemoryManager, mode); | ||
BytesToBytesMap map = | ||
new BytesToBytesMap(taskMemoryManager, blockManager, serializerManager, 1, 0.5, 1024); | ||
|
||
Thread thread = new Thread(() -> { | ||
int i = 0; | ||
long used = 0; | ||
while (i < 10) { | ||
c1.use(10000000); | ||
used += 10000000; | ||
i++; | ||
} | ||
c1.free(used); | ||
}); | ||
|
||
try { | ||
int i; | ||
for (i = 0; i < 1024; i++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
final long[] arr = new long[]{i}; | ||
final BytesToBytesMap.Location loc = map.lookup(arr, Platform.LONG_ARRAY_OFFSET, 8); | ||
loc.append(arr, Platform.LONG_ARRAY_OFFSET, 8, arr, Platform.LONG_ARRAY_OFFSET, 8); | ||
} | ||
|
||
// Starts to require memory at another memory consumer. | ||
thread.start(); | ||
|
||
BytesToBytesMap.MapIterator iter = map.destructiveIterator(); | ||
for (i = 0; i < 1024; i++) { | ||
iter.next(); | ||
} | ||
assertFalse(iter.hasNext()); | ||
} finally { | ||
map.free(); | ||
thread.join(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this line where the test hangs without the fix? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When without this line, the test still hangs. The test thread hangs on the deadlock with the other thread of running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line just makes sure |
||
for (File spillFile : spillFilesCreated) { | ||
assertFalse("Spill file " + spillFile.getPath() + " was not cleaned up", | ||
spillFile.exists()); | ||
} | ||
} | ||
} | ||
|
||
} |
Uh oh!
There was an error while loading. Please reload this page.