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

flags: Clone to avoid modifying os.Args #2195

Merged
merged 2 commits into from
Nov 6, 2023
Merged

Conversation

mqasimsarfraz
Copy link
Member

@mqasimsarfraz mqasimsarfraz commented Nov 3, 2023

If we try to shrink args (to drop '--sort ...') e.g from top file --sort -writes -m 10 --timeout 10 --interval 10 we end up reusing the underlying array and hence the original os.Args end up getting modified resulting in top file -m 10 --timeout 10 --interval 10 --interval 10. The commit clones the slice to ensure os.Args stay untouched and evaluated correctly later on.

Testing done

before the PR

→ ./kubectl-gadget  snapshot process --sort pid  --all-namespaces
K8S.NODE                                   K8S.NAMESPACE                             K8S.POD                                   K8S.CONTAINER                             COMM             PID                  UID        GID       
minikube-docker                            gadget                                    gadget-76f66                              gadget                                    gadgettracerman  3591435              0          0         
minikube-docker                            kube-system                               storage-provisioner                       storage-provisioner                       storage-provisi  3269857              0          0         
minikube-docker                            kube-system                               coredns-6d4b75cb6d-9dsjr                  coredns                                   coredns          3269733              0          0         
minikube-docker                            kube-system                               kube-proxy-swnds                          kube-proxy                                kube-proxy       3269478              0          0         
minikube-docker                            kube-system                               kube-apiserver-minikube-docker            kube-apiserver                            kube-apiserver   3268122              0          0         
minikube-docker                            kube-system                               kube-controller-manager-minikube-docker   kube-controller-manager                   kube-controller  3268080              0          0         
minikube-docker                            kube-system                               etcd-minikube-docker                      etcd                                      etcd             3268070              0          0         
minikube-docker                            kube-system                               kube-scheduler-minikube-docker            kube-scheduler                            kube-scheduler   3268062              0          0   

After the PR

→ ./kubectl-gadget  snapshot process --sort pid  --all-namespaces
K8S.NODE                                   K8S.NAMESPACE                             K8S.POD                                   K8S.CONTAINER                             COMM             PID                  UID        GID       
minikube-docker                            kube-system                               kube-scheduler-minikube-docker            kube-scheduler                            kube-scheduler   3268062              0          0         
minikube-docker                            kube-system                               etcd-minikube-docker                      etcd                                      etcd             3268070              0          0         
minikube-docker                            kube-system                               kube-controller-manager-minikube-docker   kube-controller-manager                   kube-controller  3268080              0          0         
minikube-docker                            kube-system                               kube-apiserver-minikube-docker            kube-apiserver                            kube-apiserver   3268122              0          0         
minikube-docker                            kube-system                               kube-proxy-swnds                          kube-proxy                                kube-proxy       3269478              0          0         
minikube-docker                            kube-system                               coredns-6d4b75cb6d-9dsjr                  coredns                                   coredns          3269733              0          0         
minikube-docker                            kube-system                               storage-provisioner                       storage-provisioner                       storage-provisi  3269857              0          0         
minikube-docker                            gadget                                    gadget-76f66                              gadget                                    gadgettracerman  3591435              0          0     

Note: You need sort before --all-namespace to ensure while shrinking the args we modify the order of items in removeSplitSortArgs to reproduce the issue.

@@ -2,7 +2,7 @@ name: Inspektor Gadget CI
env:
REGISTRY: ghcr.io
CONTAINER_REPO: ${{ github.repository }}
GO_VERSION: 1.20.10
Copy link
Member

Choose a reason for hiding this comment

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

Why is this upgrade necessary for this PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

To have slices.Clone(), I mean looking at what slices.Clone() does, we can also do (using append):

args := append([]string{}, os.Args[1:]...) // clone to avoid modifying the original os.Args

But should be fine to go to 1.21. What do you say?

Copy link
Member

Choose a reason for hiding this comment

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

IMO, I would avoid upgrading it unless it is strictly necessary or it provides a big advantage. And, I consider this doesn't seem the case.

However, let's see what other maintainers think.

Copy link
Member

@flyth flyth Nov 3, 2023

Choose a reason for hiding this comment

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

I think 1.21 with its maps and slices packages and the new min() and max() funcs alone are worth the upgrade as we use those things constantly. And this is timed just after a release, so there's plenty of time ahead of us to make sure it's running well. So my opinion is: go for it.

The release notes state that Go 1.21 no longer runs on Win 7 & 8 and older MacOS versions, but I don't know if the binaries it produces are affected as well - we should check for that and maybe add that to the release notes.

(But maybe this should get its own PR prior to this one)

Copy link
Member Author

Choose a reason for hiding this comment

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

(But maybe this should get its own PR prior to this one)

Yeah, maybe it is a better idea to open a separate PR for golang 1.21 and gather more use-cases.

args := append([]string{}, os.Args[1:]...) // clone to avoid modifying the original os.Args

If the above approach looks good, I can unblock this fix and we can continue with golang 1.21 separately?

Choose a reason for hiding this comment

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

I'll suggest not to tie these two things together. Unblock this PR by using that approach and add a comment saying it should be changed once we use go1.21, then in another PR we can discuss the go1.21 implications.

Copy link
Member

Choose a reason for hiding this comment

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

I am fine having golang version bumped but I would rather have a dedicated PR and a more detailed commit message.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense. I would open a separate PR for bumping golang version. For now I switched to different approach with a comment.

Copy link
Member Author

Choose a reason for hiding this comment

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

I opened #2206 to update golang version.

args := slices.Clone(os.Args) // clone to avoid modifying the original os.Args
args = removeSplitSortArgs(args)
Copy link
Member

Choose a reason for hiding this comment

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

Good catch!

This is another solution but I think your proposal is cleaner:

// removeSplitSortArgs removes the --sort flag with its arg, if it isn't in the
// merged form of --sort=foo
func removeSplitSortArgs(args []string) []string {
	for i := 0; i < len(args); i++ {
		if args[i] == "--sort" {
			// Remove also the next element as it is the arg of --sort
			ret := make([]string, 0, len(args)-2)
			ret = append(ret, args[:i]...)
			return append(ret, args[i+2:]...)
		}
	}
	return args
}

// removeHelpArg removes the --help flag
func removeHelpArg(args []string) []string {
	for i := 0; i < len(args); i++ {
		if args[i] == "--help" || args[i] == "-h" {
			ret := make([]string, 0, len(args)-1)
			ret = append(ret, args[:i]...)
			return append(ret, args[i+1:]...)
		}
	}
	return args
}

Copy link
Member Author

Choose a reason for hiding this comment

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

This is another solution but I think your proposal is cleaner

Yeah, Also cloning one level above ensure it is done for all following function.

@mauriciovasquezbernal
Copy link
Member

Perhaps you can also include the commit from #2192, so we get all the fixes in the same PR?

@@ -2,7 +2,7 @@ name: Inspektor Gadget CI
env:
REGISTRY: ghcr.io
CONTAINER_REPO: ${{ github.repository }}
GO_VERSION: 1.20.10
Copy link
Member

Choose a reason for hiding this comment

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

I am fine having golang version bumped but I would rather have a dedicated PR and a more detailed commit message.

@@ -187,7 +188,8 @@ func ParseEarlyFlags(cmd *cobra.Command) error {
cmd.FParseErrWhitelist.UnknownFlags = false
}()
// temporary workaround for https://github.com/inspektor-gadget/inspektor-gadget/pull/2174#issuecomment-1780923952
args := removeSplitSortArgs(os.Args[1:])
args := slices.Clone(os.Args) // clone to avoid modifying the original os.Args
Copy link
Member

Choose a reason for hiding this comment

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

Rather than golang 1.21 Clone() would a copy() do the trick?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, that should also do the trick. I read this to confuse myself more :D and then decided to go for whatever slices will give us in future.

mqasimsarfraz and others added 2 commits November 6, 2023 11:40
If we try to shrink args (to drop '--sort ...') we end up
reusing the underlying array and hence the original os.Args
end up getting modified. The commit clones the slice
to ensure os.Args stay untouched and evaluated correctly
later on.

Signed-off-by: Qasim Sarfraz <qasimsarfraz@microsoft.com>
Use ParseEarlyFlags() on main to be sure flags from the host package
are parsed when host.Init() is called.

Signed-off-by: Mauricio Vásquez <mauriciov@microsoft.com>
Copy link
Member

@flyth flyth left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@mqasimsarfraz
Copy link
Member Author

Thanks for reviews!

@mqasimsarfraz mqasimsarfraz merged commit 7d12644 into main Nov 6, 2023
50 checks passed
@mqasimsarfraz mqasimsarfraz deleted the qasim/clone-os-args branch November 6, 2023 16:49
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.

None yet

5 participants