[swift-server-dev] Posix Module

Johannes Weiß johannesweiss at apple.com
Sun Oct 30 13:53:56 CDT 2016


> On 30 Oct 2016, at 6:45 pm, Paulo Faria <paulo at zewo.io> wrote:
> 
>> ARC might insert 'release' calls at any point.
> 
> Are you sure this is true? `errno` is stored at the TLS. The only way "ARC might insert 'release' calls at any point.”  is if that point is in another thread. And if that `deinit` is called in another thread it won’t affect the `errno` of the current thread. What am I missing here?

I did speak to Joe Groff who's working on the Swift compiler team before about that and he confirmed that there are issues regarding that. I know `errno` is thread-safe (because it's stored in thread-local storage) but the problem can manifest even single-threaded code.

 Let's assume this code:

--- SNIP ---
public class SomeClass {
    public let someValue: Int = 42
    deinit {
        /* some failing syscall */
    }
}

let x = SomeClass()
let rv = write(x.someValue, nil, 0)
let errnoSave = errno
if rv != 0 {
    raise POSIXError(code: errnoSave)
}
--- SNAP ---

The instance `x` isn't needed anymore as soon as we have called write. So the compiler might put this code in there:

--- SNIP ---
let x = SomeClass()
let rv = write(x.someValue, nil, 0)
/* ARC generated */ x.release()
let errnoSave = errno /* wrong errno value :( */
if rv != 0 {
    raise POSIXError(code: errnoSave)
}
--- SNAP ---

and this would be causing a problem as x.release() would trigger the deinit.

Now I'm not saying this will happen every single time but it might happen depending on your code, your Swift compiler version and your optimisation levels.

Cheers,
  Johannes


> 
>> On Oct 30, 2016, at 4:11 PM, Johannes Weiß via swift-server-dev <swift-server-dev at swift.org> wrote:
>> 
>> Hi,
>> 
>> Well, correct handling of POSIX functions in Swift is unfortunately a bit harder than just re-exporting Glibc/Darwin depending on the platform.
>> 
>> Errno is an issue. In _many_ libraries I have seen code like this:
>> 
>> let rv = some_syscall(params)
>> if tv != 0 {
>>   throw POSIXError(code: errno)
>> }
>> 
>> this looks correct but technically it isn't. There's no guarantee in Swift that between calling 'some_syscall' and capturing 'errno', errno isn't overridden. ARC might insert 'release' calls at any point. Unfortunately, release calls might cause 'deinit's to be run and they might use syscalls (which could override errno).
>> 
>> So yes, just re-exporting Glibc/Darwin is easy but using these functions correctly is hard.
>> 
>> Another assumption I have seen in Swift libraries is assuming that a successful system call resets errno to 0, that's not true either.
>> 
>> But as others have said, this might be a swift-{users,evolution} question?
>> 
>> Cheers,
>> Johannes
>> 
>> 
>>> On 28 Oct 2016, at 4:51 pm, Helge Heß via swift-server-dev <swift-server-dev at swift.org> wrote:
>>> 
>>> Hi,
>>> 
>>> I guess this kinda belongs here:
>>> 
>>> I wonder whether we can have a standard Posix module with all the standard Posix stuff in it to avoid the
>>> 
>>> #if os(Linux)
>>>  import Glibc
>>> #else
>>>  import Darwin
>>> #endif
>>> 
>>> for things which are standardised in Posix (and hence the same, even on Windoze). I currently have an `xsys` module to alias the definitions, but this is kinda crap :-)
>>> 
>>> https://github.com/NozeIO/Noze.io/tree/master/Sources/xsys
>>> 
>>> Or is there a better way to do this already?
>>> 
>>> Thanks,
>>> Helge
>>> 
>>> _______________________________________________
>>> swift-server-dev mailing list
>>> swift-server-dev at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-server-dev
>> 
>> _______________________________________________
>> swift-server-dev mailing list
>> swift-server-dev at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-server-dev
> 
> 



More information about the swift-server-dev mailing list