Re: CFReadStreamHasBytesAvailable locks up my threads on 10.3.9
Re: CFReadStreamHasBytesAvailable locks up my threads on 10.3.9
- Subject: Re: CFReadStreamHasBytesAvailable locks up my threads on 10.3.9
- From: Becky Willrich <email@hidden>
- Date: Tue, 19 Apr 2005 13:42:18 -0700
The changes to CFNetwork from 10.3.8 to 10.3.9 are very limited, to put
it mildly; the only change in HTTP handling was to make the chunked
header parser a bit more lenient. Do you know if the server is sending
back a chunked response? Is SSL in the mix?
Can you sample your application when it gets in the locked-up state and
post the results? Run your application until it wedges, then from the
command line, execute:
> sample <name of the application> 5
This will cause a text file to be written out to /tmp; it will contain
a call-trace of where your program's spent its time. If you open it,
you should see one or both threads in CFReadStreamHasBytesAvailable;
the interesting bit is what happens within that call.
Thanks,
REW
On Apr 19, 2005, at 12:02 PM, Justin Greenfield wrote:
Hi guys..
In my app, I have 2 threads that run in the background, performing
downloads via HTTP. In each thread, a URL object is created and
downloaded. My code just polls the stream to see if it has bytes
available and accumulate the incoming data in one of our own objects
to be returned.
This code has worked flawlessly since 10.2 and although though it's
probably not the most elegant implementation, it's fine for us
(downloads that are a few bytes to a few hundred kilobytes in size).
Since 10.3.9 was released, however, things have gone south... In our
app, the call to CFReadStreamHasBytesAvailable will start blocking at
some point (after a couple of my URL objects are downloaded), so my
Get() method never returns and the thread which is waiting on it so it
can process the next query is rendered useless, and my application
stops getting new data.
This only seems to happen with HTTPStreams to a CGI that returns a
small amount of data, usually less than 200 bytes.
The Get() method looks like this:
CxData CxUrl::Get ()
{
CFReadStreamRef stream = CreateStream();
CxData data(0);
CFStreamError err;
bool done = false;
if (::CFReadStreamOpen(stream))
{
while (!done)
{
uint8 buf[1024];
CFIndex bytesRead = 0;
if (::CFReadStreamHasBytesAvailable(stream))
bytesRead = ::CFReadStreamRead(stream, buf, 1024);
if (bytesRead < 0)
{
err = ::CFReadStreamGetError(stream);
done = true;
}
else if (bytesRead == 0)
{
if (::CFReadStreamGetStatus(stream) == kCFStreamStatusAtEnd)
done = true;
}
else
{
CxData temp((void*)buf, bytesRead);
data += temp;
}
}
::CFReadStreamClose(stream);
}
else
err = ::CFReadStreamGetError(stream);
ProcessResponseHeader(stream);
::CFRelease(stream);
return data;
}
Once I figured out that it was CFReadStreamHasBytesAvailable that was
causing my lockup, I slightly changed the Get method to look like
this:
CxData CxUrl::Get ()
{
CFReadStreamRef stream = CreateStream();
CxData data(0);
CFStreamError err;
bool done = false;
if (::CFReadStreamOpen(stream))
{
while (!done)
{
uint8 buf[1024];
CFIndex bytesRead = 0;
CFStreamStatus streamStatus = ::CFReadStreamGetStatus(stream);
//if (::CFReadStreamHasBytesAvailable(stream))
if (streamStatus == kCFStreamStatusOpen)
{
bytesRead = ::CFReadStreamRead(stream, buf, 1024);
streamStatus = ::CFReadStreamGetStatus(stream);
}
if (bytesRead < 0)
{
err = ::CFReadStreamGetError(stream);
done = true;
}
else if (bytesRead == 0)
{
if (::CFReadStreamGetStatus(stream) == kCFStreamStatusAtEnd)
done = true;
}
else
{
CxData temp((void*)buf, bytesRead);
data += temp;
if (streamStatus == kCFStreamStatusAtEnd)
done = true;
}
}
::CFReadStreamClose(stream);
}
else
err = ::CFReadStreamGetError(stream);
ProcessResponseHeader(stream);
::CFRelease(stream);
return data;
}
This seems to help in some cases, but now it will occasionally crash
in CFReadStreamRead....
Thread 6 Crashed:
0 libobjc.A.dylib 0x90831204 objc_msgSend + 0x24
1 com.apple.CFNetwork 0x927fb70c _CFNetConnectionResponseIsComplete +
0x28
2 com.apple.CFNetwork 0x927fb6cc readFromConnection + 0x174
3 com.apple.CFNetwork 0x927f23a4 httpRequestRead + 0x124
4 com.apple.CoreFoundation 0x901f38ac CFReadStreamRead + 0x180
5 edu.ou.ocs.weatherscope 0x00039880 CxUrl::Get() + 0x78
6 edu.ou.ocs.weatherscope 0x00078ec8
DxGraphManager::MessageUpdateConfig(bool) + 0x1f8
7 edu.ou.ocs.weatherscope 0x000781f0 DxGraphManager::OnMessage(long) +
0x84
8 edu.ou.ocs.weatherscope 0x00041dc8 CxThread::RunLoop() + 0x54
9 edu.ou.ocs.weatherscope 0x00041d5c CxThread::TaskProc(void*) + 0x1c
10 ...ple.CoreServices.CarbonCore 0x902f6b90 PrivateMPEntryPoint + 0x4c
11 libSystem.B.dylib 0x90024910 _pthread_body + 0x28
As this has seriously broken our application, I need some help to
figure out how to work around this.... Any ideas??
Thanks,
Justin
--
Justin Greenfield
email@hidden
Oklahoma Climatological Survey - Software Development Group
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden