pact-foundation / pact-net

.NET version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.

Home Page:https://pact.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ruby interpreter continues to run after test completion, locking bin directory

jklaus opened this issue · comments

While making changes to the pact responses I noticed it seemed my DLLs were not being replaced. After manually trying to go out and delete the bin contents I saw the folder was still locked. I then killed VS and it was still locked. Task manager showed two Ruby Interpreter processes running. After killing those processes I am able to clean my bin folder. I am seeing this behavior consistently with any consumer test leveraging 2.0.7beta. Obviously this isn't happening for our consumers using version 1.3.2.

@jklaus Can you please create a repro project that you can share?

Yeah no problems, a simple repro project would be awesome.

Why is killing processes on windows so hard?!?!

@bethesque That is a great question! 😄

@bethesque 1) I'm concerned how it will behave on our build server. 2) Its hacky to have to kill a process like that.

@jklaus @bethesque has been running into some issues killing windows processes on some stuff she has been working on, so it's a comment about that. Pact-Net should 100% take care of killing the process, so if it's not, we need to fix it.

Yeah, sorry @jklaus, it was a wail of frustration because I spent a LOT of time trying to work out how to get the underlying pact library to politely kill the process through the same command line interface that starts it, and ended up giving up in defeat and asking the wrapper library maintainers to just kill the process by whatever means were available to them. It was a very unsatisfactory solution and it still bugs me.

@jklaus I cannot reproduce this issue. Can you try again with the latest version? Without a sample project that reproduces this issue, I can't really do much.

@bethesque - np, I get the frustration. I've been fighting VS17 since we've migrated all of our projects from VS15. With this mornings update (15.3.1 IIRC) things seem to be getting better though.

@neilcampbell - I'll try to circle the wagons on this today. I need to wrap a few other things up first though.

@jklaus Any update on this one?

@neilcampbell I've got exactly the same issue

@adamrodger Oh really, are you able to create a repo project and help me diagnose the issue. I would really like to get this fixed.

Also:
Are you using the latest beta?
What VS version?
What .NET version?
What OS version?
Do you have local admin permissions on the machine?
What test framework and version are you using?
What test runner are you using to run the test?

@adamrodger That is strange I have tried to reproduce on about 3 different machines without any luck, so not sure what is going on.

Can you pull down the PactNet solution and run the samples, and does that have the same effect on your machine? Is it the consume or provider tests or both that are causing the issue?

I'm getting an even worse problem now than just the files remaining locked. Because the mock provider doesn't shut down, if you then go and delete a consumer expectation and re-run your tests, it's still written to the resulting pact file even though it's now been deleted from your tests. All previous interactions are remembered between test runs! Process:

  1. Run all your consumer expectation tests
  2. Observe the pact file contains all expected interactions
  3. Delete the pact file
  4. Comment out one of your expectation tests
  5. Run just one test
  6. Observe that the created pact file contains every interaction, even the one you deleted and even though you only ran one test
  7. Kill the ruby process in task manager
  8. Run just one test again
  9. Observe that the created pact file now only contains that one interaction

I've also noticed that the ruby process doesn't stay running every single time. I think it might be when one of your tests fails (does that stop the Dispose() being called or something?)

Yeah the mock provider will maintain the interactions it's seen, so it really needs to shutdown after the test suite has run.

That's interesting we stop the mock provider when mockProvider.Build() is called or when the app domain unloads via AppDomain.CurrentDomain.DomainUnload, so it should cover those scenarios. If you could do some investigation, that would be amazing!

Could even be something to do with debugging?

I just tried debugging a test, and pressing stop in the resharper test runner rather than play, and that seems to prevent the app domain unload hook from firing. I think that might be the culprit?

Yep I think that is the problem. The issue is that I don't know how to solve it. When using stop in a debug session the process is being killed immediately, so the unload/stop handlers will never fire. See https://stackoverflow.com/questions/11023944/stop-debugging-event-in-c-sharp.

I'm not sure what to do here, other than to document the issue and ask people to terminate the ruby process or have another supervisor process that monitors the test session and kills the ruby process when the test session is terminated.

Thoughts?

@adamrodger Unfortunately there is no way to kill a child process when the parent dies using the .NET managed process class, however you can with some interop code. https://stackoverflow.com/questions/3235218/how-terminate-child-processes-when-parent-process-terminated-in-c-sharp. The problem with COM interop is it doesn't really translate cross platform.

I would prefer to kill the process on termination rather than on the next run.

Do you think we should hold up the release build from being dropped due to this flaw?

@adamrodger I think I will leave it as it is for now and not try to detect and prevent reusing the ruby process, because this will never happen on a build server and really a user should be producing the pact artefacts on a build server.

Agreed. You wouldn't push from your local machine.