0

When running on Linux (only tried on Linux), the following code seems to leak 1 anon_inode, and 2 pipe file descriptors, according to lsof:

CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
client.close();

If, however, client.execute() is called one or more times, the leak does not happen.

CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
client.execute(new HttpGet("http://stackoverflow.com/questions/23966483"), null);
client.close();

Full sample code:

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.util.concurrent.ExecutionException;

public class Benchmark {

    public static void main(String[] args) throws ExecutionException, InterruptedException, IOException  {
        printFileDescriptorCounts();
        for(int i = 0; i < 20; i++) {
            CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
            client.start();
            //client.execute(new HttpGet("http://stackoverflow.com/questions/23966483"), null);
            client.close();
            printFileDescriptorCounts();
        }
    }

    // not portable -- Linux only
    private static void printFileDescriptorCounts() throws IOException {
        String processId = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        String cmd = String.format("lsof -p %s | grep 'anon_inode\\|pipe' | awk '{ print $NF; }' | sort | uniq -c", processId);
        Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
        try {
            for(String line; (line = br.readLine()) != null; ) {
                System.out.print(line.replace("\n", "\t"));
            }
            System.out.println();
        } finally {
            br.close();
            process.destroy();
        }
    }

}

I see

  3 pipe
  1 anon_inode      5 pipe
  2 anon_inode      7 pipe
  3 anon_inode      9 pipe
  4 anon_inode     11 pipe
  5 anon_inode     13 pipe
  6 anon_inode     15 pipe
  7 anon_inode     17 pipe
  8 anon_inode     19 pipe
  9 anon_inode     21 pipe
 10 anon_inode     23 pipe
 11 anon_inode     25 pipe
 12 anon_inode     27 pipe
 13 anon_inode     29 pipe
 14 anon_inode     31 pipe
 15 anon_inode     33 pipe
 16 anon_inode     35 pipe
 17 anon_inode     37 pipe
 18 anon_inode     39 pipe
 19 anon_inode     41 pipe
 20 anon_inode     43 pipe

If I uncomment the execute line, the leak disappears.

  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe
  3 pipe

(1) Is the intended/expected behavior, or is this a bug?

(2) Why/how does this happen?

Charles
  • 48,924
  • 13
  • 96
  • 136
Paul Draper
  • 64,883
  • 37
  • 172
  • 246

1 Answers1

1

It looks like a defect in the I/O reactor state management logic. Please raise a JIRA with the project.

https://issues.apache.org/jira/browse/HTTPCORE

ok2c
  • 24,351
  • 4
  • 53
  • 61
  • I filed the [issue](https://issues.apache.org/jira/browse/HTTPASYNC-77). Thanks for [fixing](http://svn.apache.org/viewvc?view=revision&revision=1598890) it (so soon!), Oleg :) – Paul Draper May 31 '14 at 18:55