FileProvider icon indicating copy to clipboard operation
FileProvider copied to clipboard

Crash AFTER trying to retrieve contents of directory from FTP

Open gouen95 opened this issue 7 years ago • 10 comments

Hi, I'm trying to list down the contents of directory from a ftp server.

iOS: 11.2 XCode: 9.2, Swift 4

Here is the crash error : *** -[FilesProvider.FileProviderStreamTask respondsToSelector:]: message sent to deallocated instance 0x1c01c4ec0

Below is the code :

        let credential = URLCredential(user: hostList![row].username!, password: hostList![row].password!, persistence: .permanent)
        
        let ftpFileProvider = FTPFileProvider(baseURL: URL(string: hostList![row].serverUrl!)!, passive: true, credential: credential, cache: nil)
        
        ftpFileProvider?.contentsOfDirectory(path: "", completionHandler: { (contents, error) in
            print(error)
            
            for file in contents {
                print("Name: \(file.name)")
                print("Size: \(file.size)")
                print("Creation Date: \(file.creationDate)")
                print("Modification Date: \(file.modifiedDate)")
            }
        }) 

gouen95 avatar Jan 03 '18 08:01 gouen95

You get this error every time?

amosavian avatar Jan 03 '18 09:01 amosavian

Yes, unfortunately. : (

gouen95 avatar Jan 03 '18 09:01 gouen95

This sample code has a flaw. It does not retain ftpFileProvider instance object. You must store it as a global variable or as instance variable.

amosavian avatar Jan 03 '18 09:01 amosavian

Hi, thank you for the quick reply. I've tried to make it as an instance variable. The issue still persist. I'm sorry if I'm unfamiliar with the framework implementation.

Below is the code of my whole controller.

//
//  ContentListingViewController.swift
//  

import UIKit
import FilesProvider

class ContentListingViewController: UIViewController {
    
    //MARK:- Variables
    var host: HostBean?
    var ftpFileProvider: FTPFileProvider?
    
    //MARK:- Application Lifecycles
    override func viewDidLoad() {
        super.viewDidLoad()

        if host != nil {
            listDirectories()
        }
    }

    //MARK:- Private Functions
    private func listDirectories() {
        let credential = URLCredential(user: (host?.username!)!, password: (host?.password!)!, persistence: .permanent)
        
        ftpFileProvider?.delegate = self as FileProviderDelegate
        
        ftpFileProvider = FTPFileProvider(baseURL: URL(string: (host?.serverUrl!)!)!, passive: true, credential: credential, cache: nil)
        
        ftpFileProvider?.contentsOfDirectory(path: "/", completionHandler: { (contents, error) in
            print(error)
            
            for file in contents {
                print("Name: \(file.name)")
                print("Size: \(file.size)")
                print("Creation Date: \(file.creationDate)")
                print("Modification Date: \(file.modifiedDate)")
            }
        })
    }
}

extension ContentListingViewController: FileProviderDelegate {
    func fileproviderSucceed(_ fileProvider: FileProviderOperations, operation: FileOperationType) {
        switch operation {
        case .copy(source: let source, destination: let dest):
            print("\(source) copied to \(dest).")
        case .remove(path: let path):
            print("\(path) has been deleted.")
        default:
            print("\(operation.actionDescription) from \(operation.source) to \(String(describing: operation.destination)) succeed")
        }
    }
    
    func fileproviderFailed(_ fileProvider: FileProviderOperations, operation: FileOperationType, error: Error) {
        switch operation {
        case .copy(source: let source, destination: let dest):
            print("copy of \(source) failed. huh? \(dest)")
        case .remove:
            print("file can't be deleted.")
        default:
            print("\(operation.actionDescription) from \(operation.source) to \(String(describing: operation.destination)) failed")
        }
    }
    
    func fileproviderProgress(_ fileProvider: FileProviderOperations, operation: FileOperationType, progress: Float) {
        switch operation {
        case .copy(source: let source, destination: let dest):
            print("Copy\(source) to \(dest): \(progress * 100) completed.")
        default:
            break
        }
    }
}

gouen95 avatar Jan 03 '18 10:01 gouen95

My test unit is passing on my mac. My apps work well too. I cant reproduce :/

amosavian avatar Jan 03 '18 14:01 amosavian

Hi, I've been trying a few public ftp server out there and try to find out if any of them is same with my own desktop ftp server. I've found a public ftp server which is ftp://speedtest.tele2.net/ (username: anonymous, no password), this ftp server caused the application to crash while others don't.. I don't understand why this is happening hope it helps.

Edit : new crash error

objc[4597]: Class _NSZombie_OS_xpc_uuid is implemented in both ?? (0x1c4248df0) and ?? (0x1c4248ee0). One of the two will be used. Which one is undefined.
2018-01-05 16:24:57.788994+0800 TestFTP[4597:1119160] [MC] Lazy loading NSBundle MobileCoreServices.framework
2018-01-05 16:24:57.790122+0800 TestFTP[4597:1119160] [MC] Loaded MobileCoreServices.framework
2018-01-05 16:26:11.914376+0800 TestFTP[4597:1119160] *** -[FilesProvider.FileProviderStreamTask respondsToSelector:]: message sent to deallocated instance 0x1c01cb310

gouen95 avatar Jan 05 '18 07:01 gouen95

The problem was zombie objects. Thanks for your report. Adding these lines has fixed issue as far as I tested.

amosavian avatar Jan 05 '18 22:01 amosavian

Im having a similar crash. Using the example code for retrieving directory contents. I am retaining the FTPFileProvider. The crash happens immediately AFTER the completion block returns. The contents are retrieved properly then the app crashes with EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

example code

class CameraFileManager {
  
  let ipAddress: URL
  let documentProvider: FTPFileProvider?
  
  init(ipAddress: URL) {
    self.ipAddress = ipAddress
    
    self.documentProvider = FTPFileProvider(baseURL: ipAddress)
  }
  
  func getCameraName() {
    ///tmp/fuse_d/NAME/

    documentProvider?.contentsOfDirectory(path: "/tmp/fuse_d/NAME/", rfc3659enabled: false, completionHandler: {
      contents, error in
      for file in contents {
        print("Name: \(file.name)")
        print("Size: \(file.size)")
        print("Creation Date: \(file.creationDate)")
        print("Modification Date: \(file.modifiedDate)")
      }
    })
  }
}```

buba447 avatar Apr 21 '18 17:04 buba447

Heres a zombie trace for the error

screen shot 2018-04-21 at 10 58 42 am

buba447 avatar Apr 21 '18 17:04 buba447

@buba447 Please pull latest commit and check again

amosavian avatar Apr 22 '18 09:04 amosavian