libgit2 needs an API for non-blocking (asynchronous) network I/O #5865
Replies: 3 comments
-
Sorry to let this issue linger with no comments @thiloschulz. I was coincidentally pretty neck deep in our networking stack, and I was giving this some thought while I was in there. #5286 You mention that libssh2 and WinHTTP both have non-blocking APIs. I think that the bigger problem here is that we've basically plumbed the entirety of our network implementation with blocking assumptions, for better or worse. So I don't think that the problem is underlying support, but what we've done on top of that. This is certainly possible to unwind, but I think it will be a bit challenging. And finding a way to do it without making a breaking change to the API will be tough as well. I think that @pks-t has done a little work with a Curious: did you get an opportunity to look at this? If so, I'd love to know what you discovered in your investigation. |
Beta Was this translation helpful? Give feedback.
-
I am aware of that. Hence this discussion item.
On the contrary. It is impossible to get non-blocking semantics from an implementation that is built around blocking I/O, but it is trivial to build a blocking I/O API around a non-blocking one. Classically, a user application must implement an event loop (POSIX) or message loop (Windows). libgit2 should provide file descriptors / handles to the application, together with the event type we're expecting, to the user application. Obviosuly, libgit2 must implement a state machine, so that the application can feed received events to libgit2 which then does the right thing depending which stage we're at.
Due to the multitude of transports that libgit2 supports, I did not want to put in the effort before I heard from you. If you'd like however, I could try to get the libssh2 backed transport non-blocking and show you the results. |
Beta Was this translation helpful? Give feedback.
-
Alright. I believe the API can be made fully backwards-compatible. I have set up a proof of concept here: If you use another scheme than git_remote_callbacks for telling the user application which events to wait for, such as mandating the user application calls a function like git_remote_get_events() that must be called after GIT_EAGAIN you can even retain full compatibility for the ABI. The networking stack will require an overhaul, though I suspect it's not as bad as it sounds. For a push or pull operation, there are only a few isolated places, where networking operations actually take place. We just need to split up these functions and keep state between calls. The whole network stack seems to be a tad messy to me. libgit2 currently offers git_remote_connect() and git_remote_disconnect(). As a naive user, I'd expect I can connect to a server, do as many git_remote_push() or git_remote_pull() operations in between as I want while staying connected, and call git_remote_disconnect() to end the connection. But that's not the case, git_remote_fetch() always disconnects after it has finished. So having these functions be part of the API is kind of pointless. Also, the ssh transport needs you to specify a GIT_DIRECTION_PUSH / PULL - why not simply open and close ssh channels in the same session, just as is required for the current operation? Are there any other transports that require this direction ugliness? It would be nice if I one could do away with restrictions like these if such deep reaching changes to the network stack are made. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I want to present my users with a connection status window and a "cancel" button if a network operation takes too long. This sensible use-case is impossible to implement with libgit2 at present.
Calls into libgit2 for network operations block, most timeouts are not run-time configurable and in some cases (such as on the windows platform) are set to infinite.
It should be the choice of the user application to use a blocking or non-blocking scheme, but libgit2 takes that choice away, and for no good reason either. libssh2 as well as WinHTTP do provide asynchronous networking I/O mechanisms.
What really should happen is that all networking in libgit2 is implemented using asynchronous I/O (yes, that includes any DNS resolving) and the synchronous API, as it exists now, is built on top of that.
I may find some time at the end of the year to take a look at the libssh/winhttp transports and think of a good asynchronous API. But given that I am not very familiar with libgit2 code and git networking this would probably take me considerably longer than those who implemented networking for libgit2 in the first place.
Beta Was this translation helpful? Give feedback.
All reactions