diff --git a/CHANGELOG.md b/CHANGELOG.md index a7b33e2f6..dea4d5e1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ BUG FIXES: * client/artifact: Handle tars where file in directory is listed before directory [GH-2524] * driver/exec: Properly set file/dir ownership in chroots [GH-2552] + * driver/docker: Fix panic in Docker driver on Windows [GH-2614] * server: Reject non-TLS clients when TLS enabled [GH-2525] * server: Fix a panic in plan evaluation with partial failures and all_at_once set [GH-2544] diff --git a/Vagrantfile b/Vagrantfile index bbddcb0fe..1d5f74273 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -20,7 +20,8 @@ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential curl git- liblxc1 lxc-dev lxc-templates \ gcc-5-aarch64-linux-gnu binutils-aarch64-linux-gnu \ libc6-dev-i386 linux-libc-dev:i386 \ - gcc-5-arm-linux-gnueabihf gcc-5-multilib-arm-linux-gnueabihf binutils-arm-linux-gnueabihf + gcc-5-arm-linux-gnueabihf gcc-5-multilib-arm-linux-gnueabihf binutils-arm-linux-gnueabihf \ + gcc-mingw-w64 binutils-mingw-w64 # Setup go, for development of Nomad SRCROOT="/opt/go" diff --git a/scripts/build.sh b/scripts/build.sh index fde86bfb1..dd7147921 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -64,11 +64,11 @@ for target in $targets; do ;; "windows_386") echo "==> Building windows 386..." - CGO_ENABLED=1 GOARCH="386" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_386/nomad.exe" + CGO_ENABLED=1 CXX=i686-w64-mingw32-g++ CC=i686-w64-mingw32-gcc GOARCH="386" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_386/nomad.exe" ;; "windows_amd64") echo "==> Building windows amd64..." - CGO_ENABLED=1 GOARCH="amd64" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_amd64/nomad.exe" + CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc GOARCH="amd64" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_amd64/nomad.exe" ;; "darwin_amd64") echo "==> Building darwin amd64..." diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go index ceedee1f4..27d6ace0c 100644 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -185,7 +185,6 @@ type BackupFileReader struct { // Read will attempt to read the security descriptor of the file. func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { r := &BackupFileReader{f, includeSecurity, 0} - runtime.SetFinalizer(r, func(r *BackupFileReader) { r.Close() }) return r } @@ -196,6 +195,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { if err != nil { return 0, &os.PathError{"BackupRead", r.f.Name(), err} } + runtime.KeepAlive(r.f) if bytesRead == 0 { return 0, io.EOF } @@ -207,6 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { func (r *BackupFileReader) Close() error { if r.ctx != 0 { backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + runtime.KeepAlive(r.f) r.ctx = 0 } return nil @@ -223,7 +224,6 @@ type BackupFileWriter struct { // Write() will attempt to restore the security descriptor from the stream. func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { w := &BackupFileWriter{f, includeSecurity, 0} - runtime.SetFinalizer(w, func(w *BackupFileWriter) { w.Close() }) return w } @@ -234,6 +234,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { if err != nil { return 0, &os.PathError{"BackupWrite", w.f.Name(), err} } + runtime.KeepAlive(w.f) if int(bytesWritten) != len(b) { return int(bytesWritten), errors.New("not all bytes could be written") } @@ -245,6 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { func (w *BackupFileWriter) Close() error { if w.ctx != 0 { backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + runtime.KeepAlive(w.f) w.ctx = 0 } return nil diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index 8c15e4124..b955e886c 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -79,7 +79,6 @@ func makeWin32File(h syscall.Handle) (*win32File, error) { if err != nil { return nil, err } - runtime.SetFinalizer(f, (*win32File).closeHandle) return f, nil } @@ -103,7 +102,6 @@ func (f *win32File) closeHandle() { // Close closes a win32File. func (f *win32File) Close() error { f.closeHandle() - runtime.SetFinalizer(f, nil) return nil } @@ -166,6 +164,12 @@ func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, er if wait { r = <-c.ch } + + // runtime.KeepAlive is needed, as c is passed via native + // code to ioCompletionProcessor, c must remain alive + // until the channel read is complete. + runtime.KeepAlive(c) + err = r.err if err == syscall.ERROR_OPERATION_ABORTED { if f.closing { @@ -188,6 +192,7 @@ func (f *win32File) Read(b []byte) (int, error) { var bytes uint32 err = syscall.ReadFile(f.handle, b, &bytes, &c.o) n, err := f.asyncIo(c, f.readDeadline, bytes, err) + runtime.KeepAlive(b) // Handle EOF conditions. if err == nil && n == 0 && len(b) != 0 { @@ -207,7 +212,9 @@ func (f *win32File) Write(b []byte) (int, error) { } var bytes uint32 err = syscall.WriteFile(f.handle, b, &bytes, &c.o) - return f.asyncIo(c, f.writeDeadline, bytes, err) + n, err := f.asyncIo(c, f.writeDeadline, bytes, err) + runtime.KeepAlive(b) + return n, err } func (f *win32File) SetReadDeadline(t time.Time) error { @@ -219,3 +226,7 @@ func (f *win32File) SetWriteDeadline(t time.Time) error { f.writeDeadline = t return nil } + +func (f *win32File) Flush() error { + return syscall.FlushFileBuffers(f.handle) +} diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go index a822e4314..b1d60abb8 100644 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -4,6 +4,7 @@ package winio import ( "os" + "runtime" "syscall" "unsafe" ) @@ -28,6 +29,7 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } + runtime.KeepAlive(f) return bi, nil } @@ -36,6 +38,7 @@ func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } + runtime.KeepAlive(f) return nil } @@ -52,5 +55,6 @@ func GetFileID(f *os.File) (*FileIDInfo, error) { if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } + runtime.KeepAlive(f) return fileID, nil } diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go index b85b2eef4..f85f4a9f2 100644 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -2,6 +2,9 @@ package winio +// #include +import "C" + import ( "errors" "io" @@ -21,7 +24,7 @@ import ( type securityAttributes struct { Length uint32 - SecurityDescriptor *byte + SecurityDescriptor unsafe.Pointer InheritHandle uint32 } @@ -87,7 +90,11 @@ func (f *win32MessageBytePipe) CloseWrite() error { if f.writeClosed { return errPipeWriteClosed } - _, err := f.win32File.Write(nil) + err := f.win32File.Flush() + if err != nil { + return err + } + _, err = f.win32File.Write(nil) if err != nil { return err } @@ -227,12 +234,13 @@ func makeServerPipeHandle(path string, securityDescriptor []byte, c *PipeConfig, mode |= cPIPE_TYPE_MESSAGE } - var sa securityAttributes - sa.Length = uint32(unsafe.Sizeof(sa)) + sa := &securityAttributes{} + sa.Length = uint32(unsafe.Sizeof(*sa)) if securityDescriptor != nil { - sa.SecurityDescriptor = &securityDescriptor[0] + sa.SecurityDescriptor = C.CBytes(securityDescriptor) + defer C.free(sa.SecurityDescriptor) } - h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, &sa) + h, err := createNamedPipe(path, flags, mode, cPIPE_UNLIMITED_INSTANCES, uint32(c.OutputBufferSize), uint32(c.InputBufferSize), 0, sa) if err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go index c5e369bae..039daaac6 100644 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -11,6 +11,31 @@ import ( var _ unsafe.Pointer +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + var ( modkernel32 = windows.NewLazySystemDLL("kernel32.dll") modwinmm = windows.NewLazySystemDLL("winmm.dll") @@ -51,7 +76,7 @@ func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -64,7 +89,7 @@ func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintpt newport = syscall.Handle(r0) if newport == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -76,7 +101,7 @@ func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -88,7 +113,7 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -106,7 +131,7 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -128,7 +153,7 @@ func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances handle = syscall.Handle(r0) if handle == syscall.InvalidHandle { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -150,7 +175,7 @@ func _createFile(name *uint16, access uint32, mode uint32, sa *securityAttribute handle = syscall.Handle(r0) if handle == syscall.InvalidHandle { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -171,7 +196,7 @@ func _waitNamedPipe(name *uint16, timeout uint32) (err error) { r1, _, e1 := syscall.Syscall(procWaitNamedPipeW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(timeout), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -183,7 +208,7 @@ func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSiz r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -195,7 +220,7 @@ func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *u r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -216,7 +241,7 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -228,7 +253,7 @@ func convertSidToStringSid(sid *byte, str **uint16) (err error) { r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -249,7 +274,7 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -261,7 +286,7 @@ func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -284,7 +309,7 @@ func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -296,7 +321,7 @@ func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, si r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -315,7 +340,7 @@ func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, ou success = r0 != 0 if true { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -327,7 +352,7 @@ func impersonateSelf(level uint32) (err error) { r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -339,7 +364,7 @@ func revertToSelf() (err error) { r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -357,7 +382,7 @@ func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -389,7 +414,7 @@ func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -410,7 +435,7 @@ func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -431,7 +456,7 @@ func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint1 r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -459,7 +484,7 @@ func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, proce r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } @@ -487,7 +512,7 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) if r1 == 0 { if e1 != 0 { - err = error(e1) + err = errnoErr(e1) } else { err = syscall.EINVAL } diff --git a/vendor/vendor.json b/vendor/vendor.json index ec1b17877..603325668 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -25,10 +25,10 @@ "revisionTime": "2016-08-22T16:14:30Z" }, { - "checksumSHA1": "L9njXCkN30+qHaLayiiA2Q9jDlY=", + "checksumSHA1": "A6wxSCZcKyTwZP9b7ErXPZE3Ijg=", "path": "github.com/Microsoft/go-winio", - "revision": "fff283ad5116362ca252298cfc9b95828956d85d", - "revisionTime": "2017-02-01T00:43:30Z" + "revision": "13736c32520969a64987228c21c138a4cfdb3720", + "revisionTime": "2017-05-03T19:50:31Z" }, { "checksumSHA1": "XeG94RjA9o/0wo9Fuw6NSRGYnjk=",