title: Too many okhttp connection threads
body: <p>I am developing an android App using Retrofit2 to fetch massive data from my server. The retrofit API calls are performed in an IntentService. The downloaded data will be stored in SQLite database using Room. There are over a few hundreds of API calls. The first around 300 calls went well. However the app crashes quickly due to the error of <code>E/NativeCrypto: AppData::create pipe(2) failed: Too many open file</code>. I looked into the Profiler graph and I can see there are so many OkHttp Connections have been built up and threads grow very fast. The app crashes when the threads reached around 350.</p>
  
  <p>Below is how retrofit is configured:</p>
  
  <pre><code>Dispatcher dispatcher = new Dispatcher();
      dispatcher.setMaxRequests(100);
      dispatcher.setMaxRequestsPerHost(50);
  
  
      OkHttpClient.Builder builder = new OkHttpClient
              .Builder()
              .dispatcher(dispatcher);
      builder.authenticator(new TokenAuthenticator(this)); 
      okHttpClient = builder
              .connectionPool(new ConnectionPool(100, 1, TimeUnit.SECONDS))
              .build();
      gson = new GsonBuilder()
              .setDateFormat("yyyy-MM-dd'T'hh:mm:ss")
              .create();
      retrofit = new Retrofit.Builder()
              .client(okHttpClient)
              .baseUrl(MainApplication.API_URL)
              .addConverterFactory(ScalarsConverterFactory.create())
              .addConverterFactory(GsonConverterFactory.create(gson))
              .build();
  DownloadApiCalls downloadapiservice = retrofit.create(DownloadApiCalls.class);
  </code></pre>
  
  <p>Below is my API interface:</p>
  
  <pre><code>public interface DownloadApiCalls {
  
  @GET("Download/test2")
  Call&lt;String&gt; test2(@Query("name") String name);
  
  @GET("Download/GetTaskList")
  Call&lt;List&lt;Project&gt;&gt; GetTaskList(@Query("userid") String userid);
  
  @GET("Download/GetTaskOwnerList")
  Call&lt;List&lt;Account&gt;&gt; GetTaskOwnerList(@Query("userid") String userid);
  
  @GET("Download/GetBusinessAreasList")
  Call&lt;List&lt;BusinessArea&gt;&gt; GetBusinessAreasList(@Query("userid") String userid);
  
  @GET("Download/GetSiteCategoryList")
  Call&lt;List&lt;SiteCategory&gt;&gt; GetSiteCategoryList(@Query("accountid") String accountid);
  
  // there are lots of API calls....
  }
  </code></pre>
  
  <p>the API calls are within a loop given the business logic nature. (There are a few hundreds sites, each site has many different types of data to be downloaded.) Below is how I make calls:</p>
  
  <pre><code>for (final Site s : siteList) {
  Call call_processblock = service.GetProcessBlockList(s.Id, lastSyncTime);
              call_processblock.enqueue(new Callback&lt;List&lt;ProcessBlock&gt;&gt;() {
                  @Override
                  public void onResponse(Call&lt;List&lt;ProcessBlock&gt;&gt; call, Response&lt;List&lt;ProcessBlock&gt;&gt; r) {
                      if (r.isSuccessful() &amp;&amp; r.code() == 200) {
                          List&lt;ProcessBlock&gt; thelist = r.body();
                          AsyncTask.execute(
                          // database operations
                          );
                      }
                  }
  
                  @Override
                  public void onFailure(Call&lt;List&lt;ProcessBlock&gt;&gt; call, Throwable t) {
  
                  }
              });
  
  
              Call call_streams = service.GetProcessStreamList(s.Id, lastSyncTime);
              call_streams.enqueue(new Callback&lt;List&lt;ProcessStream&gt;&gt;() {
                  @Override
                  public void onResponse(Call&lt;List&lt;ProcessStream&gt;&gt; call, Response&lt;List&lt;ProcessStream&gt;&gt; r) {
                      if (r.isSuccessful() &amp;&amp; r.code() == 200) {
                          List&lt;ProcessStream&gt; thelist = r.body();
                          AsyncTask.execute(
                          //database operations
                          );
                      }
                  }
  
                  @Override
                  public void onFailure(Call&lt;List&lt;ProcessStream&gt;&gt; call, Throwable t) {
  
                  }
              });
  
              Call call_lines = service.GetProcessLineList(s.Id, lastSyncTime);
              call_lines.enqueue(new Callback&lt;List&lt;ProcessLine&gt;&gt;() {
                  @Override
                  public void onResponse(Call&lt;List&lt;ProcessLine&gt;&gt; call, Response&lt;List&lt;ProcessLine&gt;&gt; r) {
                      if (r.isSuccessful() &amp;&amp; r.code() == 200) {
                          AsyncTask.execute(
                          // database operations
                          );
  
                          }
                      }
                  }
  
                  @Override
                  public void onFailure(Call&lt;List&lt;ProcessLine&gt;&gt; call, Throwable t) {
  
                  }
              });
  // there are other many API calls for the site
  }
  </code></pre>
  
  <p>As per I mentioned at beginning, the app runs well until the threads reached around 350. Below is the debug output:</p>
  
  <pre><code>E/CursorWindow: CursorWindow create() failed with -24 errno
  Could not allocate CursorWindow '/data/user/0/com.gridenvironment.ufe/databases/ufe-database.db' of size 2097152 due to error -24.
  E/NativeCrypto: AppData::create pipe(2) failed: Too many open files
  W/zygote: ashmem_create_region failed for 'indirect ref table': Too many open files
  E/NativeCrypto: AppData::create pipe(2) failed: Too many open files
  E/NativeCrypto: AppData::create pipe(2) failed: Too many open files
  </code></pre>
  
  <p>Below is the snapshot of the Profiler:
  <a href="https://i.stack.imgur.com/5NwBU.png" rel="nofollow noreferrer">Too many OkHttp Connections threads</a>    </p>
  
  <p>Have I done anything incorrectly? Why are there so many OkHttp Connections are built up and not released?
  Thanks. </p>