Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79a4e10f authored by Tomasz Mikolajewski's avatar Tomasz Mikolajewski
Browse files

Do not leak pipes in archives.

Test: None.
Bug: 20822019
Change-Id: I523d6ef985c812c2c8beb374b79f56c07e6a2f79
parent 3b135ef2
Loading
Loading
Loading
Loading
+63 −31
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.support.annotation.Nullable;
import android.util.Log;
import android.util.jar.StrictJarFile;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import libcore.io.IoUtils;
@@ -41,10 +42,13 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
@@ -58,6 +62,8 @@ import java.util.zip.ZipEntry;
public class ReadableArchive extends Archive {
    private static final String TAG = "Archive";

    @GuardedBy("mEnqueuedOutputPipes")
    final Set<ParcelFileDescriptor> mEnqueuedOutputPipes = new HashSet<>();
    final ThreadPoolExecutor mExecutor;
    private final StrictJarFile mZipFile;

@@ -251,10 +257,19 @@ public class ReadableArchive extends Archive {
        }
        final InputStream inputStream = mZipFile.getInputStream(entry);
        final ParcelFileDescriptor outputPipe = pipe[1];

        synchronized (mEnqueuedOutputPipes) {
            mEnqueuedOutputPipes.add(outputPipe);
        }

        try {
            mExecutor.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            synchronized (mEnqueuedOutputPipes) {
                                mEnqueuedOutputPipes.remove(outputPipe);
                            }
                            try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
                                    new ParcelFileDescriptor.AutoCloseOutputStream(outputPipe)) {
                                try {
@@ -270,8 +285,8 @@ public class ReadableArchive extends Archive {
                                        outputStream.write(buffer, 0, bytes);
                                    }
                                } catch (IOException | InterruptedException e) {
                                // Catch the exception before the outer try-with-resource closes the
                                // pipe with close() instead of closeWithError().
                                    // Catch the exception before the outer try-with-resource closes
                                    // the pipe with close() instead of closeWithError().
                                    try {
                                        outputPipe.closeWithError(e.getMessage());
                                    } catch (IOException e2) {
@@ -287,6 +302,14 @@ public class ReadableArchive extends Archive {
                            }
                        }
                    });
        } catch (RejectedExecutionException e) {
            IoUtils.closeQuietly(pipe[0]);
            IoUtils.closeQuietly(pipe[1]);
            synchronized (mEnqueuedOutputPipes) {
                mEnqueuedOutputPipes.remove(outputPipe);
            }
            throw new IllegalStateException("Failed to initialize pipe.");
        }

        return pipe[0];
    }
@@ -354,6 +377,15 @@ public class ReadableArchive extends Archive {
    @Override
    public void close() {
        mExecutor.shutdownNow();
        synchronized (mEnqueuedOutputPipes) {
            for (ParcelFileDescriptor outputPipe : mEnqueuedOutputPipes) {
                try {
                    outputPipe.closeWithError("Archive closed.");
                } catch (IOException e2) {
                    // Silent close.
                }
            }
        }
        try {
            mZipFile.close();
        } catch (IOException e) {