EXC_BAD_ACCESS when trying to use [NSMutableURLRequest setHTTPBodyStream]

  • I'm writing a test command-line tool that only uses Foundation. I want
    to send a file to a server using HTTP PUT. The minimal code needed to
    reproduce the problem is included at the bottom of this message.

    When I run the program, I get an EXC_BAD_ACCESS with the following
    stack trace

    #0  0x9681177b in CFWriteStreamClose ()
    #1  0x9636a8dc in spoolingClose ()
    #2  0x9681157d in _CFStreamClose ()
    #3  0x968da22f in closeRequestResources ()
    #4  0x968d58c3 in httpConnectionStateChanged ()
    #5  0x968f0f94 in sendStateChanged ()
    #6  0x968f0f1e in _CFNetConnectionErrorOccurred ()
    #7  0x968e220c in httpRequestPayloadCallBack ()
    #8  0x9680f629 in _CFStreamSignalEventSynch ()
    #9  0x967fd64e in CFRunLoopRunSpecific ()
    #10 0x967fdd38 in CFRunLoopRunInMode ()
    #11 0x96203560 in +[NSURLConnection(NSURLConnectionReallyInternal)
    _resourceLoadLoop:] ()
    #12 0x961a004d in -[NSThread main] ()
    #13 0x9619fbf4 in __NSThread__main__ ()
    #14 0x947de075 in _pthread_start ()
    #15 0x947ddf32 in thread_start ()

    The fault happens before my delegate receives a single message from
    the NSURLConnection. Any suggestions as to what I'm doing wrong?

    --
    Dave Carrigan
    <dave...>
    Seattle, WA, USA

    #import <Foundation/Foundation.h>

    @interface Uploader : NSObject
    {
    }
    - (id)initWithURL:(NSURL*)url withUploadFile:(NSString*)filename;
    - (void)connection:(NSURLConnection*)connection didReceiveResponse:
    (NSURLResponse*)theResponse;
    - (void)connection:(NSURLConnection*)connection didReceiveData:
    (NSData*)data;
    - (void)connection:(NSURLConnection*)connection didFailWithError:
    (NSError*)error;
    - (void)connectionDidFinishLoading:(NSURLConnection*)connection;
    @end

    @implementation Uploader
    - (id)initWithURL:(NSURL*)url withUploadFile:(NSString*)filename
    {
      NSMutableURLRequest* request = [NSMutableURLRequest
    requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData
    timeoutInterval:60.0];
      [request setHTTPBodyStream:[NSInputStream
    inputStreamWithFileAtPath:filename]];
      [request setHTTPMethod:@"PUT"];
      [NSURLConnection connectionWithRequest:request delegate:self];
      return self;
    }

    - (void)connection:(NSURLConnection*)connection didReceiveResponse:
    (NSURLResponse*)theResponse
    {
    }

    - (void)connection:(NSURLConnection*)connection didReceiveData:
    (NSData*)data
    {
      write(1, [data bytes], [data length]);
    }

    - (void)connection:(NSURLConnection*)connection didFailWithError:
    (NSError*)error
    {
      fprintf(stderr, "Failed\n");
      exit(1);
    }

    - (void)connectionDidFinishLoading:(NSURLConnection*)connection
    {
      fprintf(stderr, "All done\n");
      exit(0);
    }

    @end

    int main (int argc, const char * argv[]) {
      [[NSAutoreleasePool alloc] init];

      NSURL* url = [NSURL URLWithString:@"http://localhost:23456/reflect"];
      [[Uploader alloc] initWithURL:url withUploadFile:@"/etc/hosts"];
      [[NSRunLoop currentRunLoop] run];
      // Will never get here
      return 0;
    }
  • On Jan 10, 2008, at 6:57 AM, Bill Garrison wrote:

    > I think you'll need to retain your NSURLConnection instance.  It's
    > probably being released out from under you by the framework (e.g. an
    > internal autorelease pool is popped, leaving the instance released
    > but nil'd out.  When messages are sent to released (and now invalid)
    > Cocoa object instances, you'll get an EXC_BAD_ACCESS exception.
    >
    > Try [[NSURLConnection connectionWithRequest:request delegate:self]
    > retain] and see what that does.

    I've had this suggestion from a few people, so I'm going to report
    back to the list that the unretained objects is not the cause of my
    problem. I changed my code to look like:

      NSMutableURLRequest* request = [[NSMutableURLRequest
    requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData
    timeoutInterval:60.0] retain];
      NSInputStream* stream = [[NSInputStream
    inputStreamWithFileAtPath:filename] retain];
      [request setHTTPBodyStream:stream];
      [request setHTTPMethod:@"PUT"];
      [[NSURLConnection connectionWithRequest:request delegate:self]
    retain];

      ...

      NSURL* url = [[NSURL URLWithString:@"http://localhost:23456/
    reflect"] retain];

    So every autorelease object I'm creating now has an explicit retain,
    but the code still crashes.

    On a different note, is there source code around somewhere that I can
    add to gdb's search path so that I'm not stuck with reading assembly
    in gdb?

    --
    Dave Carrigan
    <dave...>
    Seattle, WA, USA
  • > I've had this suggestion from a few people, so I'm going to report
    > back to the list that the unretained objects is not the cause of my
    > problem. I changed my code to look like:

      Is the "Uploader" object that contains this code retained as well?
    You set it as the delegate of your NSURLConnection. Is it still around
    when the NSURLConnection instance you create makes calls back to your
    Uploader instance?

      The error you're reporting *is* memory-management-related.

    --
    I.S.
  • On Jan 10, 2008, at 8:52 AM, I. Savant wrote:

    >> I've had this suggestion from a few people, so I'm going to report
    >> back to the list that the unretained objects is not the cause of my
    >> problem. I changed my code to look like:
    >
    > Is the "Uploader" object that contains this code retained as well?
    > You set it as the delegate of your NSURLConnection. Is it still around
    > when the NSURLConnection instance you create makes calls back to your
    > Uploader instance?

    Yes it is, because it's not autorelease. It's alloced with [[Uploader
    alloc] initWithURL] and I never do a dealloc on it. (But just to be
    sure, I just added a retain there, with no change in the crash.)

    > The error you're reporting *is* memory-management-related.

    Yes, that seems reasonable, but the more I think about it, the more I
    think it must be a bug in the library.  Based on the stack trace, it
    seems like it's a problem with the NSInputStream object, but I even
    tried doing

      NSInputStream* stream = [[[NSInputStream ....] retain] retain]
    retain]

    to try and workaround it if something is doing an extra release, but I
    still get the same crash.

    --
    Dave Carrigan
    <dave...>
    Seattle, WA, USA
  • > Yes, that seems reasonable, but the more I think about it, the more I
    > think it must be a bug in the library.  Based on the stack trace, it
    > seems like it's a problem with the NSInputStream object, but I even
    > tried doing

      That's entirely possible, but not particularly likely as this is a
    pretty well-used part of the API. Such a simple use case surely has
    been done many times before ... ;-)

      At this point, it's probably best to isolate this problem in a test
    project (a pain, I know, but a necessary one) and see if you can
    reproduce. Post the project on one of the many file sharing sites and
    send the link to the list.

    --
    I.S.
  • On Jan 10, 2008, at 9:29 AM, Dave Carrigan wrote:

    > Yes it is, because it's not autorelease. It's alloced with
    > [[Uploader alloc] initWithURL] and I never do a dealloc on it. (But
    > just to be sure, I just added a retain there, with no change in the
    > crash.)

    I hope that was a simple typo, and that you ment to say "release" and
    not "dealloc"?

    j o a r
  • On Jan 10, 2008, at 9:33 AM, I. Savant wrote:

    >> Yes, that seems reasonable, but the more I think about it, the more I
    >> think it must be a bug in the library.  Based on the stack trace, it
    >> seems like it's a problem with the NSInputStream object, but I even
    >> tried doing
    >
    > That's entirely possible, but not particularly likely as this is a
    > pretty well-used part of the API. Such a simple use case surely has
    > been done many times before ... ;-)

    I'm thinking that this use case is slightly different since it's based
    solely on Foundation in a command-line tool without any AppKit, Cocoa,
    etc. So it's quite possible that some other commonly-used framework is
    adding something that hides the bug.

    > At this point, it's probably best to isolate this problem in a test
    > project (a pain, I know, but a necessary one) and see if you can
    > reproduce. Post the project on one of the many file sharing sites and
    > send the link to the list.

    I've already done that. In my first post, the entirety of my project
    was a single file, httptest.m, which was listed in the code at the
    bottom of the post. Anyway, I've now put the rest of the project up at

      http://www.rudedog.org/tmp/httptest.tar.gz

    if anybody wants to compile and run it.

    --
    Dave Carrigan
    <dave...>
    Seattle, WA, USA
  • > I'm thinking that this use case is slightly different since it's based
    > solely on Foundation in a command-line tool without any AppKit, Cocoa,
    > etc. So it's quite possible that some other commonly-used framework is
    > adding something that hides the bug.

      Also (slightly more) possible ... but also (slightly less) unlikely. ;-)

    > I've already done that. In my first post, the entirety of my project
    > was a single file, httptest.m, which was listed in the code at the
    > bottom of the post. Anyway, I've now put the rest of the project up at

      You know, I completely missed the main() method at the bottom. I
    blame gMail. ;-)

      Anyway, after a closer look, I see your initializer isn't quite
    right ... you should be calling super -init ...

    - (id)initMyOwnSpecialWay ...
    {
      self = [super init];
      if (self)
      {
        // Do my own initialization
      }
      return self;
    }

      I can't test your code (or my assertion) on this machine as this
    particular office is Tiger-only, but if you haven't solved it by this
    evening (East coast time), I'll take a look. My laptop was left at
    home today ...

    --
    I.S.
  • On Jan 10, 2008, at 10:01 AM, Dave Carrigan wrote:

    > I'm thinking that this use case is slightly different since it's
    > based solely on Foundation in a command-line tool without any
    > AppKit, Cocoa, etc. So it's quite possible that some other commonly-
    > used framework is adding something that hides the bug.

    Running your code in a simple Cocoa application doesn't reproduce the
    problem. I think that you should file a bug report.

    j o a r
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today