diff options
| author | Bjorn Bringert <bringert@android.com> | 2009-05-29 11:46:12 +0100 |
|---|---|---|
| committer | Bjorn Bringert <bringert@android.com> | 2009-05-29 13:28:14 +0100 |
| commit | 761e0918d30b6a3f292625b44b86dffd1538bc78 (patch) | |
| tree | 6b2cdf84b7ad5244391b18b4dbe524f071da0f29 /tests | |
| parent | 9fc2e9c965c68d56a0caf812f7f6d38d15317063 (diff) | |
| download | frameworks_base-761e0918d30b6a3f292625b44b86dffd1538bc78.zip frameworks_base-761e0918d30b6a3f292625b44b86dffd1538bc78.tar.gz frameworks_base-761e0918d30b6a3f292625b44b86dffd1538bc78.tar.bz2 | |
Unmap memory in MemoryFile.close().
As reported in http://b/issue?id=1398215 MemoryFile did not
munmap(2) the ashmem region after closing it. This
causes the process to leak virtual address space.
This change fixes the problem by calling munmap(2) in
close(). The unmapping is done by a helper method deactivate().
The change also replaces the use of an int for the
file descriptor with a FileDescriptor object to
make sure that we keep track of when the file descriptor
has been closed. I chose to implement it this way because I
will need decativate() and a FileDescriptor object in an
upcoming change that allows sending MemoryFile file
descriptors between processes.
The change also adds a number of tests for the behavior
of close(). The testCloseRead() and testCloseWrite() fail
with the old MemoryFile implementation, and testCloseLeak()
causes a segfault. They all pass now.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java index 508afcf..5161f7b 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/os/MemoryFileTest.java @@ -17,16 +17,17 @@ package com.android.unit_tests.os; import android.os.MemoryFile; +import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; -import junit.framework.TestCase; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; - -import java.util.List; import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; public class MemoryFileTest extends TestCase { @@ -94,6 +95,74 @@ public class MemoryFileTest extends TestCase { file.close(); } + // Tests that close() is idempotent + @SmallTest + public void testCloseClose() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + file.close(); + file.close(); + } + + // Tests that we can't read from a closed memory file + @SmallTest + public void testCloseRead() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + file.close(); + + try { + byte[] data = new byte[512]; + assertEquals(128, file.readBytes(data, 0, 0, 128)); + fail("readBytes() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we can't write to a closed memory file + @SmallTest + public void testCloseWrite() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + file.close(); + + try { + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + fail("writeBytes() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we can't call allowPurging() after close() + @SmallTest + public void testCloseAllowPurging() throws Exception { + MemoryFile file = new MemoryFile("MemoryFileTest", 1000000); + byte[] data = new byte[512]; + file.writeBytes(data, 0, 0, 128); + file.close(); + + try { + file.allowPurging(true); + fail("allowPurging() after close() did not throw IOException."); + } catch (IOException e) { + // this is what should happen + } + } + + // Tests that we don't leak file descriptors or mmap areas + @LargeTest + public void testCloseLeak() throws Exception { + // open enough memory files that we should run out of + // file descriptors or address space if we leak either. + for (int i = 0; i < 1025; i++) { + MemoryFile file = new MemoryFile("MemoryFileTest", 5000000); + file.writeBytes(testString, 0, 0, testString.length); + file.close(); + } + } + private static final byte[] testString = new byte[] { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5, 8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6, 2, 0, 8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1, 4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9, 5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2, |
