I still like the idea of shared memory, but since without additional threading it can’t have write access inside the new process, I don’t think that it is a solution for a webserver.
The main concern was just with developers using these universal exceptions deliberately, along with “inconsistent states” and memory leaks. So here’s a simple proposal: func unsafeCatchFatalErrorWithMemoryLeak(_ block: ()->Void) -> FatalError? What it does is execute the block, and when the fatalError function is invoked (as is the case with logic errors), the fatalError checks some thread local for the existence of this handler and performs a goto. “unsafeCatchFatalErrorWithMemoryLeak” then returns a small object with the error message. The can only be one per-call stack, and it leaks deliberately leaks the entire stack from “fatalError” back down to “unsafeCatchFatalErrorWithMemoryLeak”, and that is one reason why it is labelled “unsafe” and “withMemoryLeak”. The idea is that this is a function expressly for “high availability” applications like web servers. The server will now have some leaked objects posing no immediate danger, and some inconsistencies, primarily or entirely inside the leaked objects (It is the developer’s responsibility how this is used). The “high availability sytem” is then expected to stop accepting incoming socket connections, generate another instance of itself, handle any open connections, and exit. The interesting thing about this is that it is very easy to implement. Being an unsafe function, it is not part of the language as a catch block is, and doesn’t entirely preclude another solution in the future. On March 14, 2017 at 8:22:11 PM, Elijah Johnson (ejrx7...@gmail.com) wrote: But - that would require a dedicated thread or a thread pool to run function calls on. Definitely it lacks many of the advantages of shared objects directly in the process. I would definitely prefer a small memory leak or inconsistent state. The server could handle existing requests and restart itself if it were really an issue. A memory leak can be estimated and the server restarted after every “x” times, while an inconsistent state is something that happens in any shared server environment. The developers just don’t modify the shared state until they have ready the final object, and their array/dictionary put function call itself isn’t likely to be the fail that happened. On March 14, 2017 at 7:29:28 PM, Elijah Johnson (ejrx7...@gmail.com) wrote: Also the proxies would need to implement some protocol so that they can be de-proxied when sent back to a shared method, and the proxy object exposed to the user with a new declaration that accepts only proxies. Like using MyClass -> MyClassSharedProxy for the proxy class and class MyClass { func testReturnsObject() -> SomeClass func call(a:MyClass) -> MyClass } would become class MyClassSharedProxy : MyClass, SharedProxyProtocol { func testReturnsObject() -> SomeClassSharedProxy func call(a:MyClassSharedProxy) -> MyClassSharedProxy } for example. On March 14, 2017 at 7:15:08 PM, Elijah Johnson (ejrx7...@gmail.com) wrote: Sounds like a good idea. I assume that Swift would need to compile these proxies in advance to be sub-classes ie. binary compatible objects that will forward calls and return proxies. “Value” types can be copied as they normally are, or wrapped by the user (along with “final” objects which could be wrapped manually or made not-final). Then you’d just need a way to get your first proxy object and a way to register the process’s object. Something like func openSharedObject(pid:String) throws -> Any? // cast to expected value func registerSharedProxyObject(object:Any) // for this process I suppose the caller would have to be the one to compile these proxy objects and locate them in its own module. The advantage here is that it would be not too difficult for existing servers to make use of this, as they are already written as a single process in Swift and so they would just need to manage and pre-fork processes instead of threads. Seems like it would also have numerous uses in the systems programming domain. Then one just needs, ideally, to get a stack trace and fatal error message to the parent process if a child process crashes. On March 14, 2017 at 12:18:37 AM, Brent Royal-Gordon (br...@architechies.com) wrote: > On Mar 13, 2017, at 5:54 PM, Matthew Johnson <matt...@anandabits.com> wrote: > > I suspect you're right about this for the most part but I think we will want the ability for "failable processes" (or whatever they're called) to have read-only access to shared state that outlives them. What I can't imagine is allowing them write access to state that is shared. The problem there is that shared data in Swift always has a retain count, so we'd need some way to track when code in one of these "mini-processes" retains an external object so we can release it if it crashes. Perhaps you'd need to wrap a proxy type around shared objects (or instances containing shared objects, like Array and String) and the proxies would register themselves with the runtime as needing emergency cleanup beyond unceremonious deallocation of their "mini-process"'s memory space. This is all doable; it just needs to be designed and done. -- Brent Royal-Gordon Sent from my iPhone
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution