NSPOSIXErrorDomain Code = 12 «Невозможно выделить память» в сети 3G - PullRequest
4 голосов
/ 20 мая 2011

Я пытаюсь отправить файл на FTP-сервер в приложении для iPhone. В сети WiFi и GSM: EDGE вроде бы все нормально, но в сети 3G появляется ошибка (не всегда, но очень часто):

Ошибка домена = NSPOSIXErrorDomain Code = 12 "Операция не может быть завершено. Невозможно выделить память "

Ниже кода, где появляется ошибка:

- (void)stream:(NSStream*)aStream handleEvent:(NSStreamEvent)eventCode {

    switch( eventCode ) {
        case NSStreamEventHasSpaceAvailable: {
            if( _readDataOffset == _readDataLimit ) {
                NSInteger readDataLen = [_readStream read:[_readData mutableBytes] maxLength:kReadDataLength];
                NSLog(@"readDataLen is %d",readDataLen);
                if( -1 == readDataLen ) {
                    _error = [[_readStream streamError] retain];
                    _keepRunning = NO;
                } else if( 0 == readDataLen ) {
                    _keepRunning = NO;
                } else {
                    _readDataOffset = 0;
                    _readDataLimit = readDataLen;
                }
            }

            if( _readDataOffset != _readDataLimit ) {
                NSOutputStream* writeStream = (NSOutputStream*)aStream;

                uint8_t *buffer = (void *)[_readData bytes];

          // vvvv and here  the value of writtenDataLen is often -1 (but only on 3G network)
                NSInteger writtenDataLen = [writeStream write:&buffer[_readDataOffset] maxLength:_readDataLimit - _readDataOffset]; 


                if( writtenDataLen > 0 ) {
                    _readDataOffset += writtenDataLen;
                    _writtenDataLen += writtenDataLen;
                    [self ftpPutDidWriteInternal];
                } else if( -1 == writtenDataLen ) {
                    _error = [[writeStream streamError] retain];
                    _keepRunning = NO;
                }
            }

        } break;
        case NSStreamEventErrorOccurred: {
            _error = [aStream.streamError retain];
            _keepRunning = NO;
        } break;
    }    
}

Что может быть важно, вся посылка выполняется в отдельном потоке, который имеет свой собственный NSAutoreleasePool. Есть кто-нибудь, кто получил проблему? Любое предложение? Буду признателен.

UPDATE: Я только что проверил, что популярное приложение для iPhone "FTP On The Go" имеет ту же (?) Проблему во время отправки файла в сети 3G! Ошибка не обрабатывается, но передача останавливается.

ОБНОВЛЕНИЕ 2: Я не могу в это поверить, но это правда: SimpleFTPSample от Apple также затронут этой проблемой.

Ответы [ 2 ]

1 голос
/ 10 февраля 2012

Устранена эта ошибка с использованием операции для запроса (NSMutableUrlConnection) с @autorelease{} для основной функции

- (void)main
 NSURLConnection* connection;
    @autoreleasepool //urgently needed for 3G upload
    {

        self.currentRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"test.php"]];
        [self.currentRequest setHTTPMethod:@"PUT"];

        [self.currentRequest setHTTPBody:self.data];//inpustStream doesn't work

        connection = [NSURLConnection connectionWithRequest:self.currentRequest delegate:self];
        [connection start];

    }//end autorelease pool

        do 
        {

            [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]];
            if ([self isCancelled])
            {
                connection          = nil;
                isFailed = YES;
                break;
            }
            self.status(statusUpdateMessage);
        } 
        while (!isFailed && !isCompleted);
        [timer invalidate];//test
        timer = nil;

//corresponding of status via blocks
        self.completed(!isFailed);
        self.status(isFailed ? errorMessage : @"Completed");
        if (isFailed)
        {
            self.failed(errorMessage != nil ? errorMessage : @"Undefined error");
        }

        self.data = nil;
        self.currentRequest = nil;

        connection = nil;

}
1 голос
/ 31 мая 2011

И вот оно - решение (или, скорее, обходной путь):

вам следует установить для свойства writeStream значение false, чтобы отключить постоянное соединение по умолчанию

CFWriteStreamSetProperty( (CFWriteStreamRef)writeStreamRef, kCFStreamPropertyFTPAttemptPersistentConnection, kCFBooleanFalse ) ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...