简体   繁体   中英

read failed when passing inputstream to a different thread

I am attempting to write an InputStream to a MultiPartEntity but I keep hitting:

08-01 17:25:13.523    2737-2787/com.[project].[package].test E/Volley﹕ [12495] BasicNetwork.performRequest: Unexpected response code 401 for https://api.[project].com/
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ com.android.volley.NoConnectionError: java.io.IOException: read failed: EBADF (Bad file number)
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
08-01 17:25:13.603    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
08-01 17:25:13.604    2737-2737/com.[project].[package].test W/System.err﹕ Caused by: java.io.IOException: read failed: EBADF (Bad file number)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.IoBridge.read(IoBridge.java:482)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at java.io.FileInputStream.read(FileInputStream.java:177)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at java.io.InputStream.read(InputStream.java:162)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.content.InputStreamBody.writeTo(InputStreamBody.java:91)
08-01 17:25:13.605    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.AbstractMultipartForm.doWriteTo(AbstractMultipartForm.java:150)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.AbstractMultipartForm.writeTo(AbstractMultipartForm.java:173)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.entity.mime.MultipartFormEntity.writeTo(MultipartFormEntity.java:97)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.RequestEntityProxy.writeTo(RequestEntityProxy.java:116)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:155)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.conn.CPoolProxy.sendRequestEntity(CPoolProxy.java:149)
08-01 17:25:13.606    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:242)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:260)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:178)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
08-01 17:25:13.607    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.HttpClientStack.performRequest(HttpClientStack.java:87)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
08-01 17:25:13.608    2737-2737/com.[project].[package].test W/System.err﹕ ... 1 more
08-01 17:25:13.609    2737-2737/com.[project].[package].test W/System.err﹕ Caused by: android.system.ErrnoException: read failed: EBADF (Bad file number)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.Posix.readBytes(Native Method)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.Posix.read(Posix.java:165)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.BlockGuardOs.read(BlockGuardOs.java:230)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ at libcore.io.IoBridge.read(IoBridge.java:472)
08-01 17:25:13.610    2737-2737/com.[project].[package].test W/System.err﹕ ... 21 more

the stream is an FileInputStream returned from an AssetFileDescriptor.createInputStream()

Here I get the AssetFileDescriptor

AssetFileDescriptor file = getContext().getContentResolver().openAssetFileDescriptor(person,
                    "r");

then adding it to the multipart:

multipartRequest.addFileBody("file", file.createInputStream());

which is using the MultipartEntityBuilder :

public void addFileBody(String name, InputStream in){
    multipartEntityBuilder.addBinaryBody(name, in);
}

I am using an HttpURLConnection and am writing the body here:

this (along with the entire connection) happens on a different thread

private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
        throws IOException, AuthFailureError {
    if(request.getEntity() != null){
        connection.setDoOutput(true);
        connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
        connection.setChunkedStreamingMode(0);
        OutputStream out = connection.getOutputStream();
        request.getEntity().writeTo(out);
        out.flush();
        out.close();
    } else {

I tried googling it, however all I could find out was that it is most likely that the InputStream is closed, however I don't close it anywhere.

EDIT: seems the problem is that I am attempting to make the request from a seperate thread as this all works just fine when it happens on the same thread.

TL;DR: Thread A gets filestream and creates request object, adds stream to object. Thread B starts and takes said object, opens a connection, and attempts to read the stream/write to connection at which point the read error occurs.

[[ Turns out that s/he is reading an asset and sending it to the remote so this answer doesn't really help. I'm going to leave it up as a placeholder for now. ]]

System.err﹕ Caused by: android.system.ErrnoException: read failed: EBADF (Bad file number)

As @EJP mentioned, this is trying to tell you that by the time the background thread goes to read from the stream, it has been closed.

Since this seems to be a web-client, I suspect you are trying to read a file from a GET or POST response and the response container has been shutdown and closed by the time the thread goes to read it.

There are a couple of ways to fix this:

  • The thread making the request could read in the file itself and then pass the bytes in a buffer to the background thread for processing.

  • The thread making the request could read in the file and save it in a temporary file on disk and then hand of the temp file name to the background thread.

But regardless, the thread handling the web-request has to complete the IO on the request before the web-request container is closed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM