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

syscall: exec.Cmd.Run, os.Pipe broken on linux 2.6.23 / arm #30549

Closed
jim opened this issue Mar 3, 2019 · 8 comments
Closed

syscall: exec.Cmd.Run, os.Pipe broken on linux 2.6.23 / arm #30549

jim opened this issue Mar 3, 2019 · 8 comments
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone

Comments

@jim
Copy link

jim commented Mar 3, 2019

What did you do?

I'm writing some software for old ereaders, specifically older Kindles. I've been cross compiling on macOS 10.14 using env GOOS=linux GOARCH=arm GOARM=6 go .... This work great, except that I can't use exec.Command or any other code that relies on syscall.Pipe as it returns a function not implemented error.

I'm using exec.Cmd.Run() like so:

package main

import (
	"log"
	"os/exec"
)

func main() {
	say := exec.Command("say", "some text")
	if err := say.Run(); err != nil {
		log.Fatal(err)
	}
}

However, this more minimal case will demonstrate the issue I am seeing:

package main

import (
	"log"
	"os"
)

func main() {
	if _, _, err := os.Pipe(); err != nil {
		log.Fatal(err)
	}
}

When I run this code on the device, it fails with:

2019/03/03 18:31:59 pipe: function not implemented

I think the cause is that syscall.Pipe is implemented using pipe2 on linux/arm:

func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, 0)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

It looks like pipe2 is only supported by linux 2.6.27. I'm on 2.6.23, which is listed as the minimum in the Go system requirements.

Interestingly, there is a comment to that recognizes this situation in src/os/pipe_linux.go:

// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an error, if any.
func Pipe() (r *File, w *File, err error) {
	var p [2]int

	e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
	// pipe2 was added in 2.6.27 and our minimum requirement is 2.6.23, so it
	// might not be implemented.
	if e == syscall.ENOSYS {
		// See ../syscall/exec.go for description of lock.
		syscall.ForkLock.RLock()
		e = syscall.Pipe(p[0:])
		...

The workaround above isn't going to make a difference, though, since syscall.Pipe still calls pipe2.

You can see that there are 2 pipe2 syscalls when the program is run using strace (the full output is included below):

pipe2(0x424768, O_CLOEXEC)              = -1 ENOSYS (Function not implemented)
pipe2(0x424768, 0)                      = -1 ENOSYS (Function not implemented)

The same issue seems to be present in the sys package as well.

What did you expect to see?

No error.

What did you see instead?

2019/03/03 18:31:59 pipe: function not implemented

Solution

I have been working around this by modifying my Go distribution like so:

Changing the definition of syscall.Pipe to the following in src/syscall/linux_arm.go:

func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe(&pp)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

And then adding the following to src/syscall/zsyscall_linux_arm.go (which I realize is normally autogenerated):

func pipe(p *[2]_C_int) (err error) {
	_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
	if e1 != 0 {
		err = errnoErr(e1)
	}
	return
}

I can see this OS not being officially supported as it is rather out of date, but that would be a bit of a shame since Go's cross compiling makes developing for this kind of older hardware a really nice experience.

System details

go version go1.12 darwin/amd64
GOARCH="arm"
GOBIN=""
GOCACHE="/Users/jimb/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="linux"
GOPATH="/Users/jimb/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.12/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.12/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
GOARM="6"
CC="clang"
CXX="clang++"
CGO_ENABLED="0"
GOMOD=""
GOROOT/bin/go version: go version go1.12 darwin/amd64
GOROOT/bin/go tool compile -V: compile version go1.12
uname -v: Darwin Kernel Version 18.0.0: Wed Aug 22 20:13:40 PDT 2018; root:xnu-4903.201.2~1/RELEASE_X86_64
ProductName:	Mac OS X
ProductVersion:	10.14
BuildVersion:	18A391
lldb --version: lldb-1000.11.38.2
  Swift-4.2
gdb --version: GNU gdb (GDB) 8.1

Device info:

[root@kindle root]# uname -a
Linux kindle 2.6.26-rt-lab126 #5 Sat Sep 1 14:28:26 PDT 2012 armv6l unknown

[root@kindle root]# /lib/libc.so.6
GNU C Library stable release version 2.5, by Roland McGrath et al.
...

Here is the output of running the executable with strace showing the failed attempt to use the pipe2 syscall:

[root@kindle root]# strace ./pipe
execve("./pipe", ["./pipe"], [/* 21 vars */]) = 0
getpid()                                = 4691
sched_getaffinity(0, 8192, {1})         = 4
mmap2(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000
mmap2(NULL, 270663680, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40040000
brk(0)                                  = 0x171000
mmap2(0x400000, 541065216, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400000
clock_gettime(CLOCK_MONOTONIC, {675884, 602164659}) = 0
mmap2(0x400000, 4194304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x400000
mmap2(0x40040000, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40040000
mmap2(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x50260000
clock_gettime(CLOCK_MONOTONIC, {675884, 607141284}) = 0
mmap2(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x50270000
open("/dev/urandom", O_RDONLY)          = 3
read(3, "y\355\371^K\367\234>\232\316\214o\236p!+", 16) = 16
close(3)                                = 0
rt_sigprocmask(SIG_SETMASK, NULL, [], 8) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 616442972}) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 617493722}) = 0
sigaltstack(NULL, {ss_sp=0, ss_flags=SS_DISABLE, ss_size=0}) = 0
sigaltstack({ss_sp=0x402000, ss_flags=0, ss_size=32768}, NULL) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
gettid()                                = 4691
rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGILL, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGILL, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGTRAP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTRAP, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGABRT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGABRT, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGBUS, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGBUS, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGFPE, NULL, {SIG_IGN, [], 0}, 8) = 0
rt_sigaction(SIGFPE, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGUSR1, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGUSR1, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGSEGV, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSEGV, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGUSR2, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGUSR2, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGPIPE, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPIPE, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGALRM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGALRM, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGSTKFLT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSTKFLT, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGCHLD, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGURG, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGURG, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGXCPU, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGXCPU, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGXFSZ, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGXFSZ, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGVTALRM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGVTALRM, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGPROF, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPROF, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGWINCH, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGWINCH, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGIO, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGIO, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGPWR, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPWR, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGSYS, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSYS, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRTMIN, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_1, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_2, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_2, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_3, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_3, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_4, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_4, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_5, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_5, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_6, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_6, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_7, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_7, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_8, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_8, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_9, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_9, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_10, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_10, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_11, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_11, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_12, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_12, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_13, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_13, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_14, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_14, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_15, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_15, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_16, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_16, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_17, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_17, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_18, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_18, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_19, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_19, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_20, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_20, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_21, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_21, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_22, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_22, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_23, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_23, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_24, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_24, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_25, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_25, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_26, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_26, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_27, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_27, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_28, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_28, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_29, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_29, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_30, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_30, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_31, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_31, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_32, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGRT_32, {0x626d8, ~[], SA_STACK|SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 686322597}) = 0
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
clone(child_stack=0x437ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM) = 4692
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 693493034}) = 0
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
clone(child_stack=0x439ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM) = 4693
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
futex(0x15fc3c, FUTEX_WAIT_PRIVATE, 0, NULL) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 696677909}) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 696886847}) = 0
futex(0x4282ac, FUTEX_WAKE_PRIVATE, 1)  = 1
futex(0x15fc3c, FUTEX_WAIT_PRIVATE, 0, NULL) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 700060972}) = 0
readlinkat(AT_FDCWD, "/proc/self/exe", "/var/tmp/root/pipe", 128) = 18
fcntl(0, F_GETFL)                       = 0x2 (flags O_RDWR)
mmap2(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x50280000
fcntl(1, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(2, F_GETFL)                       = 0x2 (flags O_RDWR)
pipe2(0x424768, O_CLOEXEC)              = -1 ENOSYS (Function not implemented)
pipe2(0x424768, 0)                      = -1 ENOSYS (Function not implemented)
clock_gettime(CLOCK_REALTIME, {1551637054, 129043625}) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 711729534}) = 0
openat(AT_FDCWD, "/etc//localtime", O_RDONLY|O_LARGEFILE) = 3
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0"..., 4096) = 142
read(3, "", 4096)                       = 0
close(3)                                = 0
clock_gettime(CLOCK_REALTIME, {1551637054, 137223938}) = 0
clock_gettime(CLOCK_MONOTONIC, {675884, 719875159}) = 0
write(2, "2019/03/03 18:32:34 pipe: functi"..., 512019/03/03 18:32:34 pipe: function not implemented
) = 51
exit_group(1)                           = ?
+++ exited with 1 +++
@ALTree ALTree changed the title exec.Cmd.Run, os.Pipe broken on linux 2.6.23 / arm syscall: exec.Cmd.Run, os.Pipe broken on linux 2.6.23 / arm Mar 3, 2019
@ALTree ALTree added this to the Go1.13 milestone Mar 3, 2019
@ALTree ALTree added the NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. label Mar 3, 2019
@ALTree
Copy link
Member

ALTree commented Mar 3, 2019

Assuming your analysis is correct, it seems there are two paths forward: either we fix syscall so that it actually works on 2.6.23, or we raise the minimum kernel requirement to reflect the current situation, since it seems the reality is that not everything actually runs smoothly on 2.6.23.

cc @ianlancetaylor @tklauser

@josharian
Copy link
Contributor

(OT but I’d love to see a blog post on running Go programs on Kindles. I’ve always meant to do that and never got around to it. A mini tutorial would be awesome.)

@davecheney
Copy link
Contributor

davecheney commented Mar 4, 2019

@ALTree AFAIR the minimum kernel version for linux/arm is 2.6.27. The reference to 2.6.23 is for linux on intel platforms.

@ianlancetaylor
Copy link
Contributor

The problem is clear enough: your kernel doesn't support pipe2. In https://golang.org/cl/5833 we changed syscall.Pipe on ARM GNU/Linux to use the pipe2 system call. The description of that CL implies that pipe2 is supported on kernel version 2.6.23 for ARM. Perhaps that is wrong.

Another consideration is Android O, which has a seccomp filter. If I'm reading https://android.googlesource.com/platform/bionic/+/master/libc/SYSCALLS.TXT correctly, Android O systems only permit pipe2, not pipe. In that case if we changed syscall.Pipe to use pipe rather than pipe2 we would break Go programs running on Android O.

But we can try pipe2 first and call back to pipe. I'll send a CL.

@gopherbot
Copy link

Change https://golang.org/cl/165217 mentions this issue: syscall: on ARM GNU/Linux let Pipe fall back to pipe

@gopherbot
Copy link

Change https://golang.org/cl/165297 mentions this issue: unix: on ARM GNU/Linux let Pipe fall back to pipe

@zephyr
Copy link

zephyr commented Mar 5, 2019

@josharian You wrote:

(OT but I’d love to see a blog post on running Go programs on Kindles. I’ve always meant to do that and never got around to it. A mini tutorial would be awesome.)

Try reading the Readme of his project, it’s pretty much what you asked for.

@jim
Copy link
Author

jim commented Mar 5, 2019

@ianlancetaylor Thanks for fixing this!

@josharian No blog of this stuff yet, but as zephyr mentioned I have a bit of a hacking log here.

gopherbot pushed a commit to golang/sys that referenced this issue Mar 6, 2019
Follow CL 165217 which did this for package syscall.

Android O seems to require Pipe to call the pipe2 system call.
But kernel version 2.6.23 only supports pipe, not pipe2.
So try pipe2 first, then fall back to pipe.

Updates golang/go#30549

Change-Id: Icf21433fa046ff137c0265fa96410229def482f7
Reviewed-on: https://go-review.googlesource.com/c/sys/+/165297
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
@golang golang locked and limited conversation to collaborators Mar 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made.
Projects
None yet
Development

No branches or pull requests

7 participants