Fix leaks in HTTP::Server specs#7197
Conversation
|
The CI failure shows there are even more specs leaking open ports in other files. I'll take a look at it tomorrow. |
59a4d98 to
f256ff6
Compare
|
The |
|
@j8r No it's not. I'm mainly using it to manually detect any leaking open ports. It's not solid enough to be included in automatic tests. That being said, it would be nice if specs could automatically fail if they leak fibers or open file descriptors. I don't think this can be implemented, though. |
e0e8e33 to
e4e0a5d
Compare
fd782e2 to
24c3f37
Compare
|
This PR is ready for review. It hopefully removes all interdependencies between individual server specs, and so far it looks good. The initial example with deactivating a specific spec no longer reproduces. I've run over a thousand permutations of specs (random order + leaving some out) and found no other breaking specs. This should eliminate fiber and port leaks in most places of the stdlib spec suite. A few specs specs still leak fibers (see CI results). Some are caused by the implementation of The websocket spec The |
9a97619 to
e4e0a5d
Compare
e4e0a5d to
f8ef17f
Compare
|
@straight-shoota I'd really like to see this merged. IMHO this is as good as it's, just needs a rebase. |
f8ef17f to
a6c98eb
Compare
|
If I checkout this branch and run: bin/crystal spec spec/std/http/client/client_spec.cr I get: in four specs. I don't know what's going on... This is on mac osx. I don't know why CI is happy. |
|
I don't have a Mac, can anyone reproduce? Which specs are failing exactly? And is it this plain branch or with |
|
@straight-shoota The specs that fail for me, without
What I see happening is: the server writes the response and then does If I put However, I don't understand now why it never happens that the server ends up raising because of writing the response after waiting for And also, if you try it locally but put everything inside |
|
Okay, so it effectively happens in all the specs using However, I can't reproduce any such error on linux. So it seems to be specific to MacOS. But since it doesn't trigger on CI, there must be something else to it. Would be great if a few Mac users could test this on other machines. |
a6c98eb to
932035a
Compare
|
I'd like to see this merged. New PRs like #7610 add specs that could benefit from the spec helpers defined here. I can't debug the issues on MacOS. But they seem to be related to changes to the |
|
Oh, I thought this was already merged. Yes, let's please merge this in whatever way that works. |
932035a to
091d0ec
Compare
|
@asterite I removed the changes to |
|
|
Ooops, sry. Fixed. |
asterite
left a comment
There was a problem hiding this comment.
@straight-shoota It's working fine now, thanks!
|
Feel free to merge. Then I'll rebase the |
`#bind_tcp`, `#bind_unix` and `#bind_tls` would bind a new socket and try to add it to the server. If that failed (because the server was already closed), it would raise an error but the newly created socket would not be terminated, effectively leaking it.
Spec helper for concurrently running an `HTTP::Server` in a spec and finally closing it before continuing execution in the parent scope.
197243c to
2f07b56
Compare
This fixes several issues with
HTTP::Serverspecs.Previously, there were some weird influences between individual specs. For example, when disabling
handles exception during SSL handshake(e.g. marking itpending), the following speccloses gracefullywould fail with the following error:@RX14 had already identified reusing fildescriptors by leftover fibers as probable reason.
And in fact, a large number of specs was not fully contained and leaking either open ports or unstopped fibers.
One issue was an actual bug in
HTTP::Server#bind_tcp(and similar methods) which would bind a new socket and try to add it to the server. If that failed (because the server was already closed), it would raise an error but the newly created socket would not be terminated.The other issues were all introduced by the specs themselves, a few missing
server.close.I also added a helper
run_serverwhich starts the server in a new fiber, then yields to a block for interacting with it and finally ensures that it is properly shut down. This should avoid any breaking specs from leaking server fibers.I'm not sure if
ensure_no_ports_leakingshould stay around. It's rather rudimentary. If a open port is leaked at some point, all following specs will fail because of this.This might not fix all the issues and I still don't completely understand the reasons why exactly one spec failed when the other was deactivated. But it already improves quite a lot.
I'll try to run the specs randomized to see if there might be any other issues with couplings between specs.