Conversation
straight-shoota
left a comment
There was a problem hiding this comment.
It makes so much more sense to have the locks at this level 👍
|
I was wondering whether we could safely guarantee that all file operations are protected by a lock and maintain that in the future. And there could be a simple way to provide a bit more confidence: We could combine access to the file descriptor handle with acquiring the lock. The locking methods yield the file descriptor. It's a bit more inconvenient because we have to pass the fd handle down into the system implementations, but I don't think that should be a stopper. private def unbuffered_read(slice : Bytes) : Int32
# FdLock#read yields the fd handle, and we pass it explicitly to `system_read`
@fd_lock.read { |fd| system_read(fd, slice) }
endThe public I figure this should probably be addressed in a follow-up though. |
FdLock on all targets
|
@straight-shoota Interesting. Though |
|
Damn. I didn't notice the CI failures on Windows. |
|
There's an odd behavior on Windows where a fiber keeps calling It feels like a recursive call but a stackoverflow is never reached, so it's not. Actually, the fdlock has been closed and so |
|
The issue is that It's working on UNIX, so I thought there might be something different in the UNIX vs Win32 system implementations of I think |
|
Fixing the Now, I get a "Process terminated abnormally, the cause is unknown" when running HTTP::Client specs (will retry a broken socket) 😓 If I mark the above spec as pending, I'm down to a couple failures: There might be something about |
|
The two failures are caused by Let's check if the IO has been closed before raising, and... fixed 🎉 And it seems to have fixed the "Process terminated abnormally" of the HTTP::Client spec... which still fails, but with an explicit exception:
Which sounds just about right. We did cancel it. |
|
Allright, I think I got most of the issues cornered. I'm not so sure about the last commits for IOCP. They look okayish but I'd like another pair of 👀 |
|
Sigh, one last failure apparently: |
|
The issue is caused by 4b286bb#diff-d5a00d86dac51ee0e517a4d7b20d9f87168c36220dc1fc4cb23360b424108e61R440 It makes sense: both cases shall raise an But then the |
Instead of only protecting file descriptors on UNIX, we can take advantage of Crystal::FdLock to serialize reads and writes of files, pipes and sockets for every targets.
4b286bb to
e03b7b0
Compare
|
Rebased to bring changes from |
|
MinGW eventually fails on x86_64 with the unhelpful:
While the spec output looks fine (no failures, no errors). |

Moves
Crystal::FdLockout of the internalCrystal::Systemtypes right into the stdlib types:IO::Descriptor,FileandSocket.The change is mostly to bring the single reader/writer behavior to Windows. Still, making sure to clean everything before we close a file isn't a bad idea.
Contrary to what I thought, we don't need the single reader/writer lock to implement
Crystal::EventLoop::IOCP#shutdown(IO::FileDescriptor)because Windows providesCancelIoEx(handle, NULL)that allows to cancel all pending IO operations on a file handle. This may be extracted into its own PR.Also refactors
#system_bindand#system_listenthat currently take a block to yield errors... while the block usually returns the error. It's simpler to just return a nilable error.follow-up to #16209