Skip to content
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

Partial fix #2923: Improve javalib 64 bit UnixProcess waitFor handling #2972

Merged

Conversation

LeeTibbert
Copy link
Contributor

The goal of this PR is to reduce the defects which ProcessTest is validly reporting in Continuous Integration (CI).
This has been seen particularly often on macOS.
It is marked "Partial fix" because many hundreds of CI runs need to be monitored to see if it has the desired
effect. It is hard to prove a negative.

This PR has benefited from conversations with Arman Bilge and study of his armanbilge/epollcat repository,
particularly the kevent64 handling. Merit may go to Arman; I retain ownership of all bugs & defects.

This PR makes changes in javalib for 64 bit systems running either Linux >= 5.3 or macOS.
All 32 bit systems, older Linux systems, and systems running other operating systems
continue to use the now legacy UnixProcess/UnixProcessGen1 code.

When/if it proves itself, it could probably be extended to FreeBSD and other BSD derivative.

Reviewers will note that the new UnixProcesGen2 code does not use the C++ ProcessMonitor code.

This PR provides the basis for a second PR which will modify UnixProcessGen2 to use posix_spawn().
That method is faster than fork() and a step on the road to using an even faster upcoming uring_spawn().
Pass the hot sauce please.

Copy link
Contributor

@WojciechMazur WojciechMazur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you for your work in improving work with processes.
Overall new algorithm looks good to me, I belive you have far better knowledge of working with poll events then I do. I only have few suggestions for working with Options to make code a bit more readable and idiomatic.

Comment on lines 80 to 82
val ev =
if (_exitValue.isEmpty) "not exited"
else _exitValue.head.toString()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using a fold here for a cleaner code?

Suggested change
val ev =
if (_exitValue.isEmpty) "not exited"
else _exitValue.head.toString()
val ev = _exitValue.fold("not exited")(_.toString())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thank you for the improvement.

Copy link
Contributor Author

@LeeTibbert LeeTibbert Nov 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall new algorithm looks good to me, I belive you have far better knowledge of working with poll events then I do

Thank you for the encouragement, especially coming from the person who re-wrote the unix Process and waitFor for
Windows.

Comment on lines 88 to 92
if (_exitValue.isDefined) { // avoid wait-after-wait complexity
_exitValue.head
} else { // wait until process exits or forever, whichever comes first.
osWaitForImpl(None).getOrElse(1) // 1 == EXIT_FAILURE, unknown cause
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (_exitValue.isDefined) { // avoid wait-after-wait complexity
_exitValue.head
} else { // wait until process exits or forever, whichever comes first.
osWaitForImpl(None).getOrElse(1) // 1 == EXIT_FAILURE, unknown cause
}
_exitValue // avoid wait-after-wait complexity
.orElse(osWaitForImpl(None)) // wait until process exits or forever, whichever comes first.
.getOrElse(1) // 1 == EXIT_FAILURE, unknown cause

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 96 to 104
if (_exitValue.isDefined) { // avoid wait-after-wait complexity
true
} else {
val tv = stackalloc[timespec]()
fillTimeval(timeout, unit, tv)

// wait until process exits or times out.
osWaitForImpl(Some(tv)).isDefined
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (_exitValue.isDefined) { // avoid wait-after-wait complexity
true
} else {
val tv = stackalloc[timespec]()
fillTimeval(timeout, unit, tv)
// wait until process exits or times out.
osWaitForImpl(Some(tv)).isDefined
}
_exitValue // avoid wait-after-wait complexity
.orElse {
// wait until process exits or times out.
val tv = stackalloc[timespec]()
fillTimeval(timeout, unit, tv)
osWaitForImpl(Some(tv))
}.isDefined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@WojciechMazur WojciechMazur merged commit 3961acb into scala-native:main Nov 8, 2022
@LeeTibbert LeeTibbert added the backport candidate PR which might be backported into previous major release of SN label Nov 8, 2022
@LeeTibbert
Copy link
Contributor Author

Thank you for the merge.

After this PR has proved itself in the 0.5.0 stream for a while (weeks?), I believe
it is a candidate for the 0.4.n stream. Let's see how the CI logs go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport candidate PR which might be backported into previous major release of SN
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants