Xcode project that runs only once under xcode

I have an xcode project that runs fine under xcode the first time, but if I try to run it a second time it fails in trying to open a directory (as part if the observable view data in the view's environment). It throws an error saying "Interupted system call". I have no idea how to debug something like this, so any help would be welcomed.

Thanks in advance, Rick

Answered by DTS Engineer in 837399022
It throws an error saying "Interupted system call".

By “It” you mean “My app”, right?

If so, you need to look at where that error is coming from. The Interupted system call error is EINTR, which is an expected error code from many low-level routines. I explain this in detail in Understanding `EINTR`.

Once you understand where this is coming from, that’ll inform how you approach fixing it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

It throws an error saying "Interupted system call".

By “It” you mean “My app”, right?

If so, you need to look at where that error is coming from. The Interupted system call error is EINTR, which is an expected error code from many low-level routines. I explain this in detail in Understanding `EINTR`.

Once you understand where this is coming from, that’ll inform how you approach fixing it.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Okay, by "it" I mean that xcode is running and I open the app. I then run it within xcode and it runs fine. I then try to run it again and it fails. reporting the EINTR. Then I put a breakpoint at the first line in the code of the app and run it, again within xcode. And I then start to single step through the code. The first single step brings the app up fine, time over time. It always works in that case.

I think I understand EINTR, it's been around since the beginnings of unix. How do I determine, in a windows type app, where something is occuring? I know the error is associated with an initialization of one of my classes. If I put a breakpoint there, it clearly throws when invoking foundatiion's "contentsOfDirectory". But how can I tell why? The directory exists and I. can read it in finder, and it clearly works some of the time.

If I put a breakpoint there, it clearly throws when invoking foundatiion's contentsOfDirectory. But how can I tell why?

Such is the nature of EINTR. It doesn’t matter why it’s happening in your specific case, because it can happen on user’s machines. Thus you need to handle this.

Well, Foundation needs to handle this )-:

I presume that, if you put a do … catch block around the contentsOfDirectory(atPath:) call, you see the error coming out of that. If so, that’s clearly a bug in Foundation, or one of the system frameworks below it. It should be handling EINTR for you.

I’d appreciate you filing a bug against Foundation about this. Please post your bug number, just for the record.

Fortunately it’s easy to work around this. If it throws that error, retry the call.

Now, I also recommend a switch to contentsOfDirectory(at:includingPropertiesForKeys:options:), but that’s for other reasons. Don’t switch to that to get around this problem because, if it masks the problem, you won’t be sure whether it’s an actual fix or just a shuffle of the deckchairs.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I will try to submit a bug report shortly, but I'd like to fiddle with the code a bit more. The code is in a swift package library that has been stable for several years and there is no do/catch block - the containing method is an initialization that throws and the final code piece is just a property in an @observable class in a containing app having a try! to initialize the class.

I am using the. url version.of contentsOfDirectory. The exact code piece where it throws is

let contents = try fm.contentsOfDirectory(at: suburl, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles])

but I've also tried the path version with the same results, and I know it dies there by putting a breakpoint there and single stepping through it.

One other interesting fact is that if I open the products group and run the debug version directly from the finder, it never fails.

Finally, I don't know what you mean by 'retry the call'?

Rick

I will try to submit a bug report shortly

Please do.

I’ve been doing a bit of research about this myself and it’s clear that not all is well on the Apple side. The man pages for our directory enumeration APIs (readdir, getdirentries, getattrlistbulk, and probably others) don’t mention EINTR as a possibility. However, it’s always been the case that these can return EINTR. It won’t happen in most cases, but it can happen.

Notably, the mount_nfs man page page documents an option, intr, that tells NFS that it’s OK to fail file system operations with EINTR.

So, the first step here is to fix those man pages, and I’ve filed my own bug about that (r. 150435705).

I don't know what you mean by 'retry the call'?

This:

func listDirectory(at url: URL) throws -> [URL] {
    while true {
        do {
            return try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
        } catch {
            if !isEINTR(error) {
                throw error
            }
            // loop
        }
    }
}

As to how you write isEINTR(_:), that depends on how Foundation packages the error, and I’m not sure about that because I can’t reproduce the problem myself. It could be as simple as this:

func isEINTR(_ error: Error) -> Bool {
    let error = error as NSError
    return error.domain == NSPOSIXErrorDomain && error.code == EINTR
}

but you might need to look for a generic Foundation error and then confirm that this case using NSUnderlyingErrorKey.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Well, now I'm totally confused. I tried the app this morning and got the same results. Then I added your little code snippet to the library, ran all the tests (which succeeded), updated the app and ran it. I would have sworn it stayed in the true loop forever, but now I'm not so sure. I closed the app out of xcode, then reopened it and tried the app. It ran fine! This was with your code snippet. Then I decided to simply to go back to my original code and try it. Again, I checked all the tests, and each time I set the appropriate breakpoints to make sure the expected code was being run. Lo and behold I can't get the app to fail now. Just. tried it agaiin and it worked fine. The only difference now to the oriiginal problem is some commented out code. (your snippet).

If I had to guess now, I'd say this is an xcode problem, but I have no way to reproduce or test it. Any thoughts on where to go from here?

Rick

I don't know if this is of any interest anymore, but I thought I would follow up on some related problems. I finished debugging the app (it is not intended to be submitted to the app store and is signed locally) and went to create a release version for my own personal use.. Then I got a repeat of the failed try in FileManager. I switched back to the debug version and again the try failed. I turned off debugging and tried again. No try failure. I turned back on the debugging and the try failure was still gone. So this looks like this is an xcode problem related to debugging. In any case, I have my release verrsion installed and it works fine.

I'd say this is an xcode problem, but I have no way to reproduce or test it.

It’s fair to say that this is triggered by Xcode, but I don’t think it’s an Xcode problem. Xcode relies on LLDB and LLDB uses signals [1]. EINTR is triggered by the delivery of a signal. If the stars align — well, misalign )-: — that’ll happen while your app is within the system call that’s underlying contentsOfDirectory(at:…) and you hit this error.

Your app should be resilient is the face of EINTR and it’s not, which is the real issue here. Now, that’s not your fault, it’s Foundation’s, but that’s not much of a consolation.

each time I set the appropriate breakpoints

It’s unlikely that you’ll be able to debug this with breakpoints. That triggers more involvement by LLDB, which re-rolls the dice and, in all probability, masks the issue.

If I were in your shoes I’d use the system log to confirm the fix. That is, add log points to the that loop to see what path is follows. The system log is sufficiently lightweight that it might limits the perturbations enough to preserve the error.

For links to docs on the system log, see Your Friend the System Log.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Not as much as traditional Unix-y debuggers, but it still uses them.

Xcode project that runs only once under xcode
 
 
Q