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

os: ERROR_NO_SYSTEM_RESOURCES when making child process use os.Stdout on Windows 7 #45914

Open
AkarinVS opened this issue May 2, 2021 · 6 comments

Comments

@AkarinVS
Copy link

@AkarinVS AkarinVS commented May 2, 2021

What version of Go are you using (go version)?

$ go version
go version devel +41cf18eda7 Fri Apr 2 19:45:52 2021 +0000 linux/amd64

Does this issue reproduce with the latest release?

Yes. (Actually, no, this is a new regression, see below.)

What operating system and processor architecture are you using (go env)?

The windows program is cross compiled from linux/amd64 to windows/amd64.
The windows version is Windows 7 (version 6.1.7601), vanilla installation.

What did you do?

The following command tries to execute cmd /c echo abc and let the child process use os.Stdout.
If there is no command line argument, it will simply set cmd.Stdout = os.Stdout;
otherwise, it will create a goroutine to copy cmd.StdoutPipe() to os.Stdout.
https://play.golang.org/p/rzblvBHqLb2

package main

import (
	"io"
	"log"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("cmd", "/c", "echo", "abc")
	if len(os.Args) == 1 {
		println("bug")
		cmd.Stdout = os.Stdout
	} else {
		println("io.Copy")
		outpipe, err := cmd.StdoutPipe()
		if err != nil {
			log.Fatal(err)
		}
		defer outpipe.Close()
		go io.Copy(os.Stdout, outpipe)
	}
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
}

What did you expect to see?

C:\> test.exe
bug
abc

C:\> test.exe test
io.Copy
abc

What did you see instead?

C:\> test.exe
bug
2021/05/02 00:01:02 fork/exec c:\windows\system32\cmd.exe: Insufficient system resources exist to complete the requested service.

C:\> test.exe test
io.Copy
abc

This problem reproduces every time, even when the system is freshly rebooted, so error message is likely bogus.
Also, this bug also applies to other command line programs, and it's not specific to cmd.exe.

Debugging revealed that the error is returned by CreateProcessW, and some (e.g. rprichard/win32-console-docs#6) mentions that "CreateProcessW fails with ERROR_NO_SYSTEM_RESOURCES when used with EXTENDED_STARTUPINFO_PRESENT and an attempt is made to restrict the inherited handles. The problem appears only on Win7 OS as in your tests."

@ianlancetaylor ianlancetaylor changed the title os/exec: ERROR_NO_SYSTEM_RESOURCES when making child process use os.Stdout on Windows 7 os: ERROR_NO_SYSTEM_RESOURCES when making child process use os.Stdout on Windows 7 May 3, 2021
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented May 3, 2021

Do you know whether this has ever worked? That is, do you know whether it works with older releases of Go? Thanks.

@ianlancetaylor ianlancetaylor added this to the Backlog milestone May 3, 2021
@AkarinVS
Copy link
Author

@AkarinVS AkarinVS commented May 3, 2021

@ianlancetaylor ianlancetaylor modified the milestones: Backlog, Go1.17 May 3, 2021
@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented May 5, 2021

Does https://golang.org/cl/316269 fix this issue?

@AkarinVS
Copy link
Author

@AkarinVS AkarinVS commented May 6, 2021

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented May 8, 2021

@AkarinVS thank you for reporting the issue. I can reproduce it on Windows 7.

I googled and I found other developers already encountered similar issue. 

https://bugzilla.mozilla.org/show_bug.cgi?id=1460995

bazelbuild/bazel#8676

https://github.com/bazelbuild/bazel/pull/8793/files

https://github.com/rprichard/win32-console-docs/blob/master/src/HandleTests/CreateProcess_InheritList.cc

It appears that PROC_THREAD_ATTRIBUTE_HANDLE_LIST cannot be used with console handles on Windows 7.

I am not sure what to do here.

We can, probably, use old pre-PROC_THREAD_ATTRIBUTE_HANDLE_LIST code for this situation. But what do we do about new features that are not supported without PROC_THREAD_ATTRIBUTE_HANDLE_LIST? And that would require restoring some of our before-PROC_THREAD_ATTRIBUTE_HANDLE_LIST code.

If we decide to restore our old CreateProcess code, perhaps we could leave current version of CreateProcess as is. But, if it returns ERROR_NO_SYSTEM_RESOURCES, then call old version of CreateProcess code. This should not punish majority of users for the benefits of small group of Windows 7 users.

We could also use GetFileType to decide which version of the code to run. But I am bit fuzzy about this logic. For example, I printed GetFileType of stdin, stdout and stderr while running program above, and that is what I see:

X:\>type a
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
index 253e9e8c1f..c6c39933b6 100644
--- a/src/syscall/exec_windows.go
+++ b/src/syscall/exec_windows.go
@@ -321,6 +321,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
        fd := make([]Handle, len(attr.Files))
        for i := range attr.Files {
                if attr.Files[i] > 0 {
+
+       ft, _ := GetFileType(Handle(attr.Files[i]))
+       println("ft=", ft)
+
                        err := DuplicateHandle(p, Handle(attr.Files[i]), parentProcess, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
                        if err != nil {
                                return 0, 0, err

X:\>test
bug
ft= 2
ft= 2
ft= 2
2021/05/07 12:15:05 fork/exec C:\Windows\system32\cmd.exe: Insufficient system resources exist to complete the requested service.

X:\>test a
io.Copy
ft= 2
ft= 3
ft= 2
abc

X:\>

Alex

@AkarinVS
Copy link
Author

@AkarinVS AkarinVS commented May 11, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants