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

nsexec: Don't ignore write failures #3165

Closed
wants to merge 2 commits into from

Conversation

rata
Copy link
Member

@rata rata commented Aug 16, 2021

If write fails for some reason or manages to write less than what we
requested (e.g. disk is full), report an error.

This silence the warning when compiling on github CI, as now the
write(2) return code is not ignored.

While we could do:
ret = write(.., ret)
if (ret < 0)

as other parts of the code does, there was recently a race condition
fixed in "libct/nsenter: fix logging race in nsexec" (2bab4a5) and
seems fragile to just test for -1. Let's check that we wrote exactly
what we expect, otherwise it won't be valid json written.

For the same reason, the race condition fixed, we don't retry if we
write partial data, as that uses two different write(2) calls which
might hit the same race. Therefore, if we failed to write what we
expect, we just let the caller know.

Note that if the write fails, it is possible for the (partial) json
written to not be valid.

Signed-off-by: Rodrigo Campos rodrigo@kinvolk.io

@rata rata marked this pull request as draft August 16, 2021 16:19
@rata rata force-pushed the rata/nsexec-warning branch from ec7929f to edddca3 Compare August 16, 2021 16:28
rata added 2 commits August 16, 2021 18:30
If write fails for some reason or manages to write less than what we
requested (e.g. disk is full), report an error.

This silence the warning when compiling on github CI, as now the
write(2) return code is not ignored.

While we could do:
	ret = write(.., ret)
	if (ret < 0)

as other parts of the code does, there was recently a race condition
fixed in "libct/nsenter: fix logging race in nsexec" (2bab4a5) and
seems fragile to just test for -1. Let's check that we wrote exactly
what we expect, otherwise it won't be valid json written.

For the same reason, the race condition fixed, we don't retry if we
write partial data, as that uses two different write(2) calls which
might hit the same race. Therefore, if we failed to write what we
expect, we just let the caller know.

Note that if the write fails, it is possible for the (partial) json
written to not be valid.

Signed-off-by: Rodrigo Campos <rodrigo@kinvolk.io>
When using CGO, treat warning as errors. Warnings are quite hidden in
the CI (only shown for the compilation step, that is collapsed) and CI
is green anyways.

Ignoring the return code of write as we just added in commit
2bab4a5 would have not happened if this
was visible.

Signed-off-by: Rodrigo Campos <rodrigo@kinvolk.io>
@rata rata force-pushed the rata/nsexec-warning branch from edddca3 to bd49aa9 Compare August 16, 2021 16:30
@rata
Copy link
Member Author

rata commented Aug 16, 2021

Added a second commit to treat C warnings as errors, so the CI fails and is not so easy to miss these kind of errors in the future. Ready for review now! :)

I've tested that indeed the warning was treated as an error in the CI if I remove the "libct/nsenter: Don't ignore write failures" commit and keep "libct/nsenter: Treat CGO warnings as errors". For the CI to use the -Werror flag, it was not enough to make the change in the _gccgo.go file. I needed to do it in nsenter.go file too.

@rata rata marked this pull request as ready for review August 16, 2021 16:32
@@ -3,7 +3,7 @@
package nsenter

/*
#cgo CFLAGS: -Wall
#cgo CFLAGS: -Wall -Werror
Copy link
Member

Choose a reason for hiding this comment

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

Given that what constitutes a "warning" varies from version to version of the compiler, shouldn't this be somehow added only in the CI instead? Otherwise I imagine a lot of downstream packagers might end up having to patch it out in the future. 😬

Copy link
Contributor

Choose a reason for hiding this comment

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

Totally agree with @tianon -- it is discouraged to have -Werror in non-development builds, for the reason explained above.

It seems we can have CGO_CFLAGS=-Werror defined via environment in CI (and CI only). Maybe also add -Wextra (to nsenter.go, not via env, as otherwise runtime/cgo will fail to build, as it has -Werror -- and that's a nice demonstration of why -Werror can be bad).

Copy link
Contributor

Choose a reason for hiding this comment

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

No, we can't have -Wextra:

# github.com/opencontainers/runc/libcontainer/nsenter
cloned_binary.c: In function ‘clone_binary’:
cloned_binary.c:511:21: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘__off_t’ {aka ‘long int’} [-Wsign-compare]
  511 |         while (sent < statbuf.st_size) {
      |                     ^
cloned_binary.c:522:18: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘__off_t’ {aka ‘long int’} [-Wsign-compare]
  522 |         if (sent != statbuf.st_size)
      |                  ^~
# github.com/opencontainers/runc/libcontainer/nsenter
nsexec.c: In function ‘write_file’:
nsexec.c:202:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
  202 |         if (len != data_len) {
      |                 ^~
nsexec.c: In function ‘try_mapping_tool’:
nsexec.c:246:73: warning: unused parameter ‘map_len’ [-Wunused-parameter]
  246 | static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len)
      |                                                                  ~~~~~~~^~~~~~~
# github.com/opencontainers/runc/libcontainer/nsenter
_cgo_main.c: In function ‘crosscall2’:
_cgo_main.c:2:23: warning: unused parameter ‘fn’ [-Wunused-parameter]
    2 | void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }
      |                 ~~~~~~^~~~~~~~~~
_cgo_main.c:2:41: warning: unused parameter ‘a’ [-Wunused-parameter]
    2 | void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }
      |                                   ~~~~~~^
_cgo_main.c:2:48: warning: unused parameter ‘c’ [-Wunused-parameter]
    2 | void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }
      |                                            ~~~~^
_cgo_main.c:2:65: warning: unused parameter ‘ctxt’ [-Wunused-parameter]
    2 | void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }
      |                                                                 ^
_cgo_main.c: In function ‘_cgo_release_context’:
_cgo_main.c:4:41: warning: unused parameter ‘ctxt’ [-Wunused-parameter]
    4 | void _cgo_release_context(__SIZE_TYPE__ ctxt) { }
      |                                         ^
_cgo_main.c: In function ‘_cgo_allocate’:
_cgo_main.c:6:26: warning: unused parameter ‘a’ [-Wunused-parameter]
    6 | void _cgo_allocate(void *a, int c) { }
      |                    ~~~~~~^
_cgo_main.c:6:33: warning: unused parameter ‘c’ [-Wunused-parameter]
    6 | void _cgo_allocate(void *a, int c) { }
      |                             ~~~~^
_cgo_main.c: In function ‘_cgo_panic’:
_cgo_main.c:7:23: warning: unused parameter ‘a’ [-Wunused-parameter]
    7 | void _cgo_panic(void *a, int c) { }
      |                 ~~~~~~^
_cgo_main.c:7:30: warning: unused parameter ‘c’ [-Wunused-parameter]
    7 | void _cgo_panic(void *a, int c) { }
      |                          ~~~~^

Copy link
Member Author

Choose a reason for hiding this comment

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

@tianon @kolyshkin oh, right. Excellent point!

@kolyshkin
Copy link
Contributor

The alternative to this one is #3154.

write(logfd, json, ret);
len = write(logfd, json, ret);
if (len != ret) {
ret = -1;
Copy link
Contributor

Choose a reason for hiding this comment

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

This variable is unused below, iow this assignment is not needed.

@kolyshkin
Copy link
Contributor

If write fails for some reason or manages to write less than what we
requested (e.g. disk is full), report an error.

We are not writing to disk here, we're writing to the pipe.

Therefore, if we failed to write what we
expect, we just let the caller know.

This function does not return anything, so this statement
is not accurate.

I was thinking about how we can handle a partial write,
and decided that we don't. With that in mind, seems like
the best solution is #3168; PTAL.

@rata
Copy link
Member Author

rata commented Aug 18, 2021

@kolyshkin oh, thanks!

I was turning this PR into just treat warnings as errors on the CI. Wrote the code (it is quite simple), but then it can be quite painful when we upgrade the CI (like change the ubuntu version or the like, might reveal several new warnings). So, unsure if this has value or will be more pain than benefits.

If no one thinks we should do that change, I'll close this in a few days :)

@kolyshkin
Copy link
Contributor

I was turning this PR into just treat warnings as errors on the CI. Wrote the code (it is quite simple), but then it can be quite painful when we upgrade the CI (like change the ubuntu version or the like, might reveal several new warnings). So, unsure if this has value or will be more pain than benefits.

I think adding -Werror to CI (and CI only) makes sense and adds value. If you want to work on it, please go ahead (I guess in a new PR, let's close this one).

@kolyshkin kolyshkin closed this Aug 18, 2021
@rata rata deleted the rata/nsexec-warning branch August 31, 2021 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants