-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Negociation bug appearing when pulling in several steps (https://github.com/mirage/irmin/issues/600) #338
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the status of this issue ? |
Actually, it appeared to me (too late sadly) that this bug was not that easy to reproduce: Indeed, after attempting to mock the problem with a fake server, I was unable to get the problem again. |
I observed the following behaviour:
since this is rather static, a test case could be to dump the (binary tcp stream of the) server, and replay the replies when the client requests them... instead of trying with a real server or implementing a full server. in any case, thanks for this PR, the lengthy description, and I hope it to be released very soon now :D 🐫 🌵 |
Closed by #351 |
CHANGES: - Move to the last version of `decompress` (@dinosaure, mirage/ocaml-git#366) - Check order of entries in a tree object (bug found by @samoht, fixed by @dinosaure, mirage/ocaml-git#365) - Use `mmap` package (@dinosaure, mirage/ocaml-git#347, mirage/ocaml-git#360) - Update README.md (@tcoopman, @dinosaure, mirage/ocaml-git#337, mirage/ocaml-git#359) - `trim` the window used to pack (@pqwy, @dinosaure, mirage/ocaml-git#357, mirage/ocaml-git#358) - Use lastest version of `lru.0.3.0` (@pqwy, @dinosaure, mirage/ocaml-git#352, mirage/ocaml-git#356) - Fix smart protocol (fixed by @clecat and @dinosaure, feedbacks from @hannesm) * Pull-request mirage/ocaml-git#351, mirage/ocaml-git#350, mirage/ocaml-git#338 * Issues mirage/ocaml-git#335, mirage/ocaml-git#342, mirage/ocaml-git#346 + regression tests was added (@dinosaure) + semantics about negociation was explained (@clecat) + end-to-end tests partially done (@hannesm) - Remove `sexplib` dependency (@samoht, mirage/ocaml-git#349) - Fix smart protocol to accept empty response from `ls-remote` (bug found by @hannesm, fixed by @dinosaure, mirage/ocaml-git#348) - Add `io-page-unix` as dependency to tests `git-mirage` (@dinosaure, mirage/ocaml-git#345) - Remove deprecated `Cstruct.add_len` (replaced by `ke`) (@dinosaure, mirage/ocaml-git#345) - Use `Uri.user_info` to be able to be authentified by a service like GitHub (@linse, review by @dinosaure, mirage/ocaml-git#341, mirage/ocaml-git#343) - avoid clash between `digestif.c` and `digestif.ocaml` implementation (same for `checkseum`) * remove implementation dependencies on `git-unix` and `git-mirage` (bug found by @hannesm and @linse, fixed by @dinosaure, mirage/ocaml-git#339) This update should be fixed by `dune`'s variants and `>= digestif.0.7.2` and `>= checkseum.0.1.0` - **breaking-change** add `etmp` as already-allocated buffer to encode Git object (@dinosaure, mirage/ocaml-git#336) * add `ke.0.3` as new dependency - consumed inputs for every entries in a tree (bug found by @zspicko, fixed by @dinosaure, mirage/ocaml-git#334)
In this issue, of mirage/irmin, @zshipko found out a bug where the negotiation fails.
Origin of the problem:
During the negotiations, when the client sends several 'have' lines followed by a flush line, the server answers with Ack for every hash he posses too.
If the server has no more hash to acknowledge, he sends a Nak to the clent.
But if he acknowledged every hash, he may send a Nak to the client.
And after investigations, it appears that ocaml-git does not consume the Nak if all the hash were acknowledged. Results this situation:
Client sends:
Server sends back
The client consumes all line excepted the NACK, so when the client sends another number of 'have', the NACK is still in the input buffer:
Client sends:
Server sends back
But when the client reads the server response, he gets
And consider that all hashes from hash n + 1 to n + m are not available in the server and stops consuming the input, which leaves
in the buffer.
After that, considering the negociation has ended, the client attemps to read
Instead he gets
Which creates the error
Solution:
In order to solve the problem, we need to understand when a NAK response may be send by the server in order to consume it if necessary.
After reading the code of the git implementation in C, it appears that a NAK response will always be send by the server after a flush line, if we have the capability multi_ack or multi_ack_detailed (which we have in the issue) which corresponds to the lines 1332 to 1338 of 'smart.ml'
This case is only accesible when we have the capabilities multi_ack or multi_ack_detailed.
The solution would be to remove the if statement and try to read a new line again in all the cases:
This modification should solve the problem without breaking anything, but I'm not certain. This is why...
Further improvement:
We need some code mocking a server in order to do some integration test and ensure that we keep the right behavior after doing some modifications.
I will try to do this as soon as possible, it should allow a lot of safety in further modifications.