NSURLConnection在10.5.7下崩溃 [英] NSURLConnection crashing under 10.5.7

查看:218
本文介绍了NSURLConnection在10.5.7下崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小应用程序,下载股票价格,工作完美(多年),直到我最近升级到10.5.7。升级后,程序将在此调用上崩溃:

  NSString * currinfo = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2,escsymbol]]]; 

奇怪的是,崩溃不会马上发生。这行代码被调用了很多次,没有问题,然后程序最终会在1-2小时后由于此调用崩溃而失败。



这里有一篇长篇文章描述了我调查这个问题的尝试。我收到两个建议:(i)使调用异步(可能更好的反正)和(ii)使用NSZombieEnabled调查Objective-C对象被提前释放的可能性(此评论是响应堆栈跟踪显示失败objc_msgSend)。



我花了很多时间使调用异步(使用[[NSURLConnection alloc] initWithRequest:theRequest delegate:self]),这没有帮助。该程序最终失败,通常在10-15分钟后。在故障之前的这段时间内,许多异步调用没有任何问题,数据被返回等等。一切都很好。然后程序突然再次崩溃。



然后我打开了NSZombieEnabled。果然,当程序最终崩溃时,我得到了消息:

   -  [CFArray count]:消息发送到释放的实例0x16b90bd0 

info malloc 0x16b90bd0then yielded:



<$在0x932d1267:在__CFArrayInit
3 0x9464a138::p $ p> 0:0x93db810c在malloc_zone_malloc
1:0x946bc3d1在_CFRuntimeCreateInstance
2 0x946cd647在_CFStreamScheduleWithRunLoop
4 _Z16_scheduleRStreamPKvPv
5:0x946bf15c在CFSetApplyFunction
6:0x932b0e2b在CFNSchedulingSetScheduleReadStream
7:0x9331a310在_ZN12HTTPProtocol19createAndOpenStreamEv
8:0x9332e877在_ZN19URLConnectionLoader24loaderScheduleOriginLoadEPK13_CFURLRequest
9:0x9332d739在_ZN19URLConnectionLoader26LoaderConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl
10:0x9332dbdd在_ZN19URLConnectionLoader13processEventsEv
11:0x932d8dbf在_ZN17MultiplexerSource7performEv
12:0x946ba595在CFRunLoopRunSpecific
13:0x946bac78在CFRunLoopRunInMode
14:0x9058c530在+ [NSURLConnection的(NSURLConnectionReallyInternal)_resourceLoadLoop:]
15:0x90528e0d in - [NSThread main]
16:0x905289b4在__NSThread__main__
17:0x93de8155在_pthread_start
18:0x93de8012在thread_start

我不是阅读堆栈跟踪的专家,但是这个跟踪是否表示Apple代码中的问题,而不是我的代码?或者我可以以某种方式负责解除CFArray的分配?有没有什么办法让我进一步调查问题的原因?






(这是我的原始帖子的其余部分)



看到 stringWithContentsOfURL 已弃用,我切换到此代码:

  pathURL = [NSURL URLWithString:[NSString stringWithFormat:@http://finance.yahoo.com/d/quotes.csv?s=%@&f= l1c1p2,escsymbol]]; 

NSURLRequest * request = [NSURLRequest requestWithURL:pathURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];

responseData = [NSURLConnection sendSynchronousRequest:request returnedResponse:& response error:& error];

NSString * currinfo = nil;

if([error code]){dNSLog((@%@%d%@%@%@,[error domain],[error code],[error localizedDescription] @file:// localhost / etc / gettytab)); }

这没有帮助。在任意时间长度后,程序仍然在 sendSynchronousRequest 行崩溃,调试器中的信息如下:

  0 0x93db7286在mach_msg_trap 
1 0x93dbea7c在mach_msg
2 0x946ba04e在CFRunLoopRunSpecific
3 0x946bac78在CFRunLoopRunInMode
在CFURLConnectionSendSynchronousRequest
5 4 0x932b53eb 0x905dca4b in + [NSURLConnection sendSynchronousRequest:returningResponse:error:]

...等。

真正的崩溃可能在不同的线程:

  0 libobjc.A名为.dylib 0x965c3688 objc_msgSend + 24 
1 com.apple.CoreFoundation 0x946cc581 _CFStreamSignalEventSynch + 193
2 com.apple.CoreFoundation 0x946ba595 CFRunLoopRunSpecific + 3141
3 com.apple.CoreFoundation 0x946bac78 CFRunLoopRunInMode + 88
4 com.apple.Foundation 0x9058c530 + [NSURLConnection的(NSURLConnectionReallyInternal)_resourceLoadLoop:] + 320
5 com.apple.Foundation 0x90528e0d - [NSThread主] + 45
6 com.apple.Foundation 0x905289b4 __NSThread__main__ + 308
7 libSystem.B.dylib 0x93de8155 _pthread_start + 321
8 libSystem.B.dylib 0x93de8012 thread_start + 34

我假设是下载URL的线程。顺便说一句,错误处理代码工作正常 - 当我故意通过断开与互联网,导致错误,错误只是报告在控制台,程序不会崩溃。



这是令人难以置信的沮丧。我会非常高兴地花费尽可能多的时间跟踪问题,但我是在我的知识与gdb的极限,特别是与汇编语言。我不知道如何找出基础代码的实际问题是什么。一开始我以为可能自动释放 NSString escsymbol 不知何故被解除分配,但发送一个保留消息没有帮助。



是否有其他人遇到这个问题?

解决方案

我认为Eugene的回复在这个线程正确描述的问题;经过一些测试,这里是我总结似乎正在进行,希望一些细节,以帮助其他人坚持这个问题:



重定向的URL将定期导致失败。这发生在 NSURLConnection 的同步和异步用法中。我创建了一个测试项目来跟踪这个错误,这种崩溃会持续发生(通常在25-500次迭代之间)。在10.5.6或没有重定向网址的情况下运行相同的测试不会失败(已运行了多达20,000次迭代)。



有两种可能的解决方法: p>


  1. 不要使用重定向网址:

    显然,这并不总是可能,但如果是已知网址,你仍然可以使用简单的调用(如 stringWithContentsOfURL:),这将工作正常。 Dennis,在你的情况下,正确的服务器URL是 download.finance.yahoo.com ,而不是 finance.yahoo.com ,所以我相信这将解决你的特定问题。使用 curl ,您可以看到当您点击后一个地址时,您将获得301重定向。

  2. 使用异步调用并实现< c $ c> connection:willSendRequest:redirectResponse:

    如果你实现甚至最基本的处理这个委托方法,一切似乎都工作。如果你省略这个调用(因此让系统使用其默认实现),你会得到崩溃。对于基本实现,只需返回传递的请求:



   - (NSURLRequest * )connection:(NSURLConnection *)connection 
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
{
return request;
}

这似乎暗示苹果的实现在10.5.7,但如果任何人对任何可能发生的事情有任何见解,请来。



我已经提交了一个我的测试项目的bug到苹果 rdar:// 6936109 并引用tjw的报告(Radar 6932684)。


I have a little app that downloads stock prices and was working perfectly (for years) until my recent upgrade to 10.5.7. After the upgrade, the program would crash on this call:

NSString *currinfo = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]]];

Oddly, the crash doesn't happen right away. This line of code is called many times, with no problems, and then the program eventually fails after 1-2 hours due to a crash on this call.

I originally had a long post here describing my attempts to investigate this problem. I received two suggestions: (i) make the call asynchronous (probably better anyway) and (ii) use NSZombieEnabled to investigate the possibility that an Objective-C object is getting deallocated early (this comment was made in response to stack traces showing failure in objc_msgSend).

I spent a good deal of time making the call asynchronous (using [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]) and this didn't help. The program still failed eventually, usually after 10-15 minutes. During this interval before failure, many asynchronous calls were made without any problem, data was returned, etc. Everything was fine. Then the program crashed suddenly again.

I then turned on NSZombieEnabled. Sure enough, when the program eventually crashed I got the message:

-[CFArray count]: message sent to deallocated instance 0x16b90bd0

"info malloc 0x16b90bd0" then yielded:

0: 0x93db810c in malloc_zone_malloc
1: 0x946bc3d1 in _CFRuntimeCreateInstance
2: 0x9464a138 in __CFArrayInit
3: 0x946cd647 in _CFStreamScheduleWithRunLoop
4: 0x932d1267 in _Z16_scheduleRStreamPKvPv
5: 0x946bf15c in CFSetApplyFunction
6: 0x932b0e2b in CFNSchedulingSetScheduleReadStream
7: 0x9331a310 in _ZN12HTTPProtocol19createAndOpenStreamEv
8: 0x9332e877 in _ZN19URLConnectionLoader24loaderScheduleOriginLoadEPK13_CFURLRequest
9: 0x9332d739 in _ZN19URLConnectionLoader26LoaderConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl
10: 0x9332dbdd in _ZN19URLConnectionLoader13processEventsEv
11: 0x932d8dbf in _ZN17MultiplexerSource7performEv
12: 0x946ba595 in CFRunLoopRunSpecific
13: 0x946bac78 in CFRunLoopRunInMode
14: 0x9058c530 in +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]
15: 0x90528e0d in -[NSThread main]
16: 0x905289b4 in __NSThread__main__
17: 0x93de8155 in _pthread_start
18: 0x93de8012 in thread_start

I am no expert in reading stack traces, but doesn't this trace indicate a problem in Apple code, rather than my code? Or could I somehow be responsible for de-allocation of the CFArray in question? Is there any way for me to further investigate the cause of the problem?


(Here's the rest of my original post)

Seeing that stringWithContentsOfURL is deprecated, I switched to this code:

pathURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]];

NSURLRequest *request = [NSURLRequest requestWithURL:pathURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];

responseData = [ NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

NSString *currinfo = nil;

if ([error code]) {  dNSLog((@"%@ %d %@ %@ %@", [ error domain], [ error code], [ error localizedDescription], request, @"file://localhost/etc/gettytab"));  }

This didn't help. The program still crashes on the sendSynchronousRequest line after an arbitrary length of time, with this information in the debugger:

0   0x93db7286 in mach_msg_trap
1   0x93dbea7c in mach_msg
2   0x946ba04e in CFRunLoopRunSpecific
3   0x946bac78 in CFRunLoopRunInMode
4   0x932b53eb in CFURLConnectionSendSynchronousRequest
5   0x905dca4b in +[NSURLConnection sendSynchronousRequest:returningResponse:error:]

...etc.

The real crash might actually be in a different thread:

0   libobjc.A.dylib                 0x965c3688 objc_msgSend + 24
1   com.apple.CoreFoundation        0x946cc581 _CFStreamSignalEventSynch + 193
2   com.apple.CoreFoundation        0x946ba595 CFRunLoopRunSpecific + 3141
3   com.apple.CoreFoundation        0x946bac78 CFRunLoopRunInMode + 88
4   com.apple.Foundation            0x9058c530 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 320
5   com.apple.Foundation            0x90528e0d -[NSThread main] + 45
6   com.apple.Foundation            0x905289b4 __NSThread__main__ + 308
7   libSystem.B.dylib               0x93de8155 _pthread_start + 321
8   libSystem.B.dylib               0x93de8012 thread_start + 34

which I presume is the thread spawned to download the URL. By the way, the error handling code works fine--when I intentionally cause an error by disconnecting from the internet, the error is just reported in the console and the program doesn't crash.

This is incredibly frustrating. I would be very happy to spend as much time as necessary tracking down the problem, but I'm kind of at the limits of my knowledge with gdb and especially with assembly language. I don't know how to find out what is the actual problem for the Foundation code. At first I thought that maybe the autoreleased NSString escsymbol is somehow being deallocated, but sending it a retain message didn't help. If this were the case, how could I prove it?

Is anybody else having this problem?

解决方案

I think Eugene's reply in this thread is properly describing the problem; after some testing, here is what I've concluded seems to be going on, with hopefully some details to help others stuck with this issue:

Redirecting URLs will periodically cause failures. This happens both in the sync and async usages of NSURLConnection. I've created a test project to track down this bug, and this crash will consistently occur (typically between 25-500 iterations). Running the same test on 10.5.6 or without redirecting URLs does not fail (have run it up to 20,000 iterations).

There are two possible work-arounds:

  1. Don't use redirecting URLs:
    Obviously this isn't always possible, but if it is a known URL, you can still use the simple calls (like stringWithContentsOfURL:) and this will work fine. Dennis, in your case, the proper server URL is download.finance.yahoo.com, not finance.yahoo.com, so I believe this would fix your particular problem. Using curl you can see that you get a 301 redirect when you hit the latter address.
  2. Use the async calls and implement connection:willSendRequest:redirectResponse:
    If you implement even the most basic handling of this delegate method, everything seems to work. If you leave out this call (and thus let the system use its default implementation), you'll get the crash. For a basic implementation, just return the request that is passed in:

- (NSURLRequest *)connection:(NSURLConnection *)connection 
             willSendRequest:(NSURLRequest *)request 
            redirectResponse:(NSURLResponse *) redirectResponse
{
    return request;
}

All of this seems to suggest to me that there is something broken in Apple's implementation in 10.5.7, but if anyone else has any insights as to what might be going on, please chime in.

I have submitted a bug with my test project to Apple as rdar://6936109 and referenced tjw's report (Radar 6932684).

这篇关于NSURLConnection在10.5.7下崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆