Skip to content

Commit 10532fd

Browse files
ianlancetaylorgopherbot
authored andcommitted
runtime: change fcntl to return two values
Separate the result and the errno value, rather than assuming that the result can never be negative. Change-Id: Ib01a70a3d46285aa77e95371cdde74e1504e7c12 Reviewed-on: https://go-review.googlesource.com/c/go/+/496416 Run-TryBot: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent 9c447b7 commit 10532fd

28 files changed

+179
-109
lines changed

src/internal/syscall/unix/fcntl_unix.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import (
1414
// Implemented in the runtime package.
1515
//
1616
//go:linkname fcntl runtime.fcntl
17-
func fcntl(fd int32, cmd int32, arg int32) int32
17+
func fcntl(fd int32, cmd int32, arg int32) (int32, int32)
1818

1919
func Fcntl(fd int, cmd int, arg int) (int, error) {
20-
val := fcntl(int32(fd), int32(cmd), int32(arg))
21-
if val < 0 {
22-
return 0, syscall.Errno(-val)
20+
val, errno := fcntl(int32(fd), int32(cmd), int32(arg))
21+
if val == -1 {
22+
return int(val), syscall.Errno(errno)
2323
}
2424
return int(val), nil
2525
}

src/runtime/nbpipe_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ func TestNonblockingPipe(t *testing.T) {
3131
if runtime.Close(r) != 0 {
3232
t.Fatalf("Close(%d) failed", r)
3333
}
34-
val := runtime.Fcntl(r, syscall.F_GETFD, 0)
35-
if val >= 0 {
34+
val, errno := runtime.Fcntl(r, syscall.F_GETFD, 0)
35+
if val != -1 {
3636
t.Errorf("Fcntl succeeded unexpectedly")
37-
} else if syscall.Errno(-val) != syscall.EBADF {
38-
t.Errorf("Fcntl failed with error %v, expected %v", -val, syscall.EBADF)
37+
} else if syscall.Errno(errno) != syscall.EBADF {
38+
t.Errorf("Fcntl failed with error %v, expected %v", syscall.Errno(errno), syscall.EBADF)
3939
}
4040
}
4141

@@ -55,19 +55,19 @@ func checkIsPipe(t *testing.T, r, w int32) {
5555

5656
func checkNonblocking(t *testing.T, fd int32, name string) {
5757
t.Helper()
58-
flags := runtime.Fcntl(fd, syscall.F_GETFL, 0)
59-
if flags < 0 {
60-
t.Errorf("fcntl(%s, F_GETFL) failed: %v", name, syscall.Errno(-flags))
58+
flags, errno := runtime.Fcntl(fd, syscall.F_GETFL, 0)
59+
if flags == -1 {
60+
t.Errorf("fcntl(%s, F_GETFL) failed: %v", name, syscall.Errno(errno))
6161
} else if flags&syscall.O_NONBLOCK == 0 {
6262
t.Errorf("O_NONBLOCK not set in %s flags %#x", name, flags)
6363
}
6464
}
6565

6666
func checkCloseonexec(t *testing.T, fd int32, name string) {
6767
t.Helper()
68-
flags := runtime.Fcntl(fd, syscall.F_GETFD, 0)
69-
if flags < 0 {
70-
t.Errorf("fcntl(%s, F_GETFD) failed: %v", name, syscall.Errno(-flags))
68+
flags, errno := runtime.Fcntl(fd, syscall.F_GETFD, 0)
69+
if flags == -1 {
70+
t.Errorf("fcntl(%s, F_GETFD) failed: %v", name, syscall.Errno(errno))
7171
} else if flags&syscall.FD_CLOEXEC == 0 {
7272
t.Errorf("FD_CLOEXEC not set in %s flags %#x", name, flags)
7373
}

src/runtime/os3_solaris.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -570,12 +570,9 @@ func pipe2(flags int32) (r, w int32, errno int32) {
570570
}
571571

572572
//go:nosplit
573-
func fcntl(fd, cmd, arg int32) int32 {
573+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32) {
574574
r1, err := sysvicall3Err(&libc_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg))
575-
if r := int32(r1); r >= 0 {
576-
return r
577-
}
578-
return -int32(err)
575+
return int32(r1), int32(err)
579576
}
580577

581578
//go:nosplit

src/runtime/os_aix.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -352,12 +352,9 @@ func walltime() (sec int64, nsec int32) {
352352
}
353353

354354
//go:nosplit
355-
func fcntl(fd, cmd, arg int32) int32 {
355+
func fcntl(fd, cmd, arg int32) (int32, int32) {
356356
r, errno := syscall3(&libc_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg))
357-
if int32(r) < 0 {
358-
return -int32(errno)
359-
}
360-
return int32(r)
357+
return int32(r), int32(errno)
361358
}
362359

363360
//go:nosplit
@@ -367,8 +364,10 @@ func closeonexec(fd int32) {
367364

368365
//go:nosplit
369366
func setNonblock(fd int32) {
370-
flags := fcntl(fd, _F_GETFL, 0)
371-
fcntl(fd, _F_SETFL, flags|_O_NONBLOCK)
367+
flags, _ := fcntl(fd, _F_GETFL, 0)
368+
if flags != -1 {
369+
fcntl(fd, _F_SETFL, flags|_O_NONBLOCK)
370+
}
372371
}
373372

374373
// sigPerThreadSyscall is only used on linux, so we assign a bogus signal

src/runtime/os_dragonfly.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func kqueue() int32
6363
func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
6464

6565
func pipe2(flags int32) (r, w int32, errno int32)
66-
func fcntl(fd, cmd, arg int32) int32
66+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32)
6767
func closeonexec(fd int32)
6868

6969
// From DragonFly's <sys/sysctl.h>

src/runtime/os_freebsd.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func kqueue() int32
4848
func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
4949

5050
func pipe2(flags int32) (r, w int32, errno int32)
51-
func fcntl(fd, cmd, arg int32) int32
51+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32)
5252
func closeonexec(fd int32)
5353

5454
// From FreeBSD's <sys/sysctl.h>

src/runtime/os_linux.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -467,13 +467,9 @@ func osyield_no_g() {
467467
func pipe2(flags int32) (r, w int32, errno int32)
468468

469469
//go:nosplit
470-
func fcntl(fd, cmd, arg int32) int32 {
471-
r, _, errno := syscall.Syscall6(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
472-
ri := int32(r)
473-
if ri < 0 {
474-
return -int32(errno)
475-
}
476-
return ri
470+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32) {
471+
r, _, err := syscall.Syscall6(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
472+
return int32(r), int32(err)
477473
}
478474

479475
const (

src/runtime/os_netbsd.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func kqueue() int32
7979
func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
8080

8181
func pipe2(flags int32) (r, w int32, errno int32)
82-
func fcntl(fd, cmd, arg int32) int32
82+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32)
8383
func closeonexec(fd int32)
8484

8585
const (

src/runtime/os_openbsd_syscall2.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func nanotime1() int64
9595
//go:noescape
9696
func sigaltstack(new, old *stackt)
9797

98-
func fcntl(fd, cmd, arg int32) int32
98+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32)
9999
func closeonexec(fd int32)
100100

101101
func walltime() (sec int64, nsec int32)

src/runtime/sys_darwin.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,13 @@ func sysctlbyname_trampoline()
434434

435435
//go:nosplit
436436
//go:cgo_unsafe_args
437-
func fcntl(fd, cmd, arg int32) int32 {
438-
return libcCall(unsafe.Pointer(abi.FuncPCABI0(fcntl_trampoline)), unsafe.Pointer(&fd))
437+
func fcntl(fd, cmd, arg int32) (ret int32, errno int32) {
438+
args := struct {
439+
fd, cmd, arg int32
440+
ret, errno int32
441+
}{fd, cmd, arg, 0, 0}
442+
libcCall(unsafe.Pointer(abi.FuncPCABI0(fcntl_trampoline)), unsafe.Pointer(&args))
443+
return args.ret, args.errno
439444
}
440445
func fcntl_trampoline()
441446

@@ -538,8 +543,10 @@ func closeonexec(fd int32) {
538543

539544
//go:nosplit
540545
func setNonblock(fd int32) {
541-
flags := fcntl(fd, _F_GETFL, 0)
542-
fcntl(fd, _F_SETFL, flags|_O_NONBLOCK)
546+
flags, _ := fcntl(fd, _F_GETFL, 0)
547+
if flags != -1 {
548+
fcntl(fd, _F_SETFL, flags|_O_NONBLOCK)
549+
}
543550
}
544551

545552
// Tell the linker that the libc_* functions are to be found

src/runtime/sys_darwin_amd64.s

+11-7
Original file line numberDiff line numberDiff line change
@@ -364,17 +364,21 @@ ok:
364364
RET
365365

366366
TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
367-
MOVL 4(DI), SI // arg 2 cmd
368-
MOVL 8(DI), DX // arg 3 arg
369-
MOVL 0(DI), DI // arg 1 fd
367+
MOVQ DI, BX
368+
MOVL 0(BX), DI // arg 1 fd
369+
MOVL 4(BX), SI // arg 2 cmd
370+
MOVL 8(BX), DX // arg 3 arg
370371
XORL AX, AX // vararg: say "no float args"
371372
CALL libc_fcntl(SB)
372-
TESTL AX, AX
373-
JGT noerr
373+
XORL DX, DX
374+
CMPQ AX, $-1
375+
JNE noerr
374376
CALL libc_error(SB)
375-
MOVL (AX), AX
376-
NEGL AX // caller expects negative errno value
377+
MOVL (AX), DX
378+
MOVL $-1, AX
377379
noerr:
380+
MOVL AX, 12(BX)
381+
MOVL DX, 16(BX)
378382
RET
379383

380384
// mstart_stub is the first function executed on a new thread started by pthread_create.

src/runtime/sys_darwin_arm64.s

+11-7
Original file line numberDiff line numberDiff line change
@@ -309,18 +309,22 @@ ok:
309309

310310
TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
311311
SUB $16, RSP
312-
MOVW 4(R0), R1 // arg 2 cmd
313-
MOVW 8(R0), R2 // arg 3 arg
312+
MOVD R0, R19
313+
MOVW 0(R19), R0 // arg 1 fd
314+
MOVW 4(R19), R1 // arg 2 cmd
315+
MOVW 8(R19), R2 // arg 3 arg
314316
MOVW R2, (RSP) // arg 3 is variadic, pass on stack
315-
MOVW 0(R0), R0 // arg 1 fd
316317
BL libc_fcntl(SB)
317-
MOVD $-1, R1
318-
CMP R0, R1
318+
MOVD $0, R1
319+
MOVD $-1, R2
320+
CMP R0, R2
319321
BNE noerr
320322
BL libc_error(SB)
321-
MOVW (R0), R0
322-
NEG R0, R0 // caller expects negative errno value
323+
MOVW (R0), R1
324+
MOVW $-1, R0
323325
noerr:
326+
MOVW R0, 12(R19)
327+
MOVW R1, 16(R19)
324328
ADD $16, RSP
325329
RET
326330

src/runtime/sys_dragonfly_amd64.s

+7-3
Original file line numberDiff line numberDiff line change
@@ -385,16 +385,20 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
385385
MOVL AX, ret+48(FP)
386386
RET
387387

388-
// func fcntl(fd, cmd, arg int32) int32
388+
// func fcntl(fd, cmd, arg int32) (ret int32, errno int32)
389389
TEXT runtime·fcntl(SB),NOSPLIT,$0
390390
MOVL fd+0(FP), DI // fd
391391
MOVL cmd+4(FP), SI // cmd
392392
MOVL arg+8(FP), DX // arg
393393
MOVL $92, AX // fcntl
394394
SYSCALL
395-
JCC 2(PC)
396-
NEGL AX // caller expects negative errno
395+
JCC noerr
396+
MOVL $-1, ret+16(FP)
397+
MOVL AX, errno+20(FP)
398+
RET
399+
noerr:
397400
MOVL AX, ret+16(FP)
401+
MOVL $0, errno+20(FP)
398402
RET
399403

400404
// void runtime·closeonexec(int32 fd);

src/runtime/sys_freebsd_386.s

+7-3
Original file line numberDiff line numberDiff line change
@@ -451,13 +451,17 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
451451
MOVL AX, ret+24(FP)
452452
RET
453453

454-
// func fcntl(fd, cmd, arg int32) int32
454+
// func fcntl(fd, cmd, arg int32) (int32, int32)
455455
TEXT runtime·fcntl(SB),NOSPLIT,$-4
456456
MOVL $SYS_fcntl, AX
457457
INT $0x80
458-
JAE 2(PC)
459-
NEGL AX // caller expects negative errno
458+
JAE noerr
459+
MOVL $-1, ret+12(FP)
460+
MOVL AX, errno+16(FP)
461+
RET
462+
noerr:
460463
MOVL AX, ret+12(FP)
464+
MOVL $0, errno+16(FP)
461465
RET
462466

463467
// int32 runtime·closeonexec(int32 fd);

src/runtime/sys_freebsd_amd64.s

+7-3
Original file line numberDiff line numberDiff line change
@@ -548,16 +548,20 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
548548
MOVL AX, ret+48(FP)
549549
RET
550550

551-
// func fcntl(fd, cmd, arg int32) int32
551+
// func fcntl(fd, cmd, arg int32) (int32, int32)
552552
TEXT runtime·fcntl(SB),NOSPLIT,$0
553553
MOVL fd+0(FP), DI // fd
554554
MOVL cmd+4(FP), SI // cmd
555555
MOVL arg+8(FP), DX // arg
556556
MOVL $SYS_fcntl, AX
557557
SYSCALL
558-
JCC 2(PC)
559-
NEGQ AX // caller expects negative errno
558+
JCC noerr
559+
MOVL $-1, ret+16(FP)
560+
MOVL AX, errno+20(FP)
561+
RET
562+
noerr:
560563
MOVL AX, ret+16(FP)
564+
MOVL $0, errno+20(FP)
561565
RET
562566

563567
// void runtime·closeonexec(int32 fd);

src/runtime/sys_freebsd_arm.s

+5-2
Original file line numberDiff line numberDiff line change
@@ -387,15 +387,18 @@ TEXT runtime·kevent(SB),NOSPLIT,$0
387387
MOVW R0, ret+24(FP)
388388
RET
389389

390-
// func fcntl(fd, cmd, arg int32) int32
390+
// func fcntl(fd, cmd, arg int32) (int32, int32)
391391
TEXT runtime·fcntl(SB),NOSPLIT,$0
392392
MOVW fd+0(FP), R0 // fd
393393
MOVW cmd+4(FP), R1 // cmd
394394
MOVW arg+8(FP), R2 // arg
395395
MOVW $SYS_fcntl, R7
396396
SWI $0
397-
RSB.CS $0, R0 // caller expects negative errno
397+
MOVW $0, R1
398+
MOVW.CS R0, R1
399+
MOVW.CS $-1, R0
398400
MOVW R0, ret+12(FP)
401+
MOVW R1, errno+16(FP)
399402
RET
400403

401404
// void runtime·closeonexec(int32 fd)

src/runtime/sys_freebsd_arm64.s

+8-4
Original file line numberDiff line numberDiff line change
@@ -439,17 +439,21 @@ ok:
439439
MOVW R0, ret+48(FP)
440440
RET
441441

442-
// func fcntl(fd, cmd, arg int32) int32
442+
// func fcntl(fd, cmd, arg int32) (int32, int32)
443443
TEXT runtime·fcntl(SB),NOSPLIT,$0
444444
MOVW fd+0(FP), R0
445445
MOVW cmd+4(FP), R1
446446
MOVW arg+8(FP), R2
447447
MOVD $SYS_fcntl, R8
448448
SVC
449-
BCC ok
450-
NEG R0, R0 // caller expects negative errno
451-
ok:
449+
BCC noerr
450+
MOVW $-1, R1
451+
MOVW R1, ret+16(FP)
452+
MOVW R0, errno+20(FP)
453+
RET
454+
noerr:
452455
MOVW R0, ret+16(FP)
456+
MOVW $0, errno+20(FP)
453457
RET
454458

455459
// func closeonexec(fd int32)

src/runtime/sys_freebsd_riscv64.s

+8-4
Original file line numberDiff line numberDiff line change
@@ -420,17 +420,21 @@ ok:
420420
MOVW A0, ret+48(FP)
421421
RET
422422

423-
// func fcntl(fd, cmd, arg int32) int32
423+
// func fcntl(fd, cmd, arg int32) (int32, int32)
424424
TEXT runtime·fcntl(SB),NOSPLIT,$0
425425
MOVW fd+0(FP), A0
426426
MOVW cmd+4(FP), A1
427427
MOVW arg+8(FP), A2
428428
MOV $SYS_fcntl, T0
429429
ECALL
430-
BEQ T0, ZERO, ok
431-
NEG A0, A0 // caller expects negative errno
432-
ok:
430+
BEQ T0, ZERO, noerr
431+
MOV $-1, A1
432+
MOVW A1, ret+16(FP)
433+
MOVW A0, errno+20(FP)
434+
RET
435+
noerr:
433436
MOVW A0, ret+16(FP)
437+
MOVW ZERO, errno+20(FP)
434438
RET
435439

436440
// func closeonexec(fd int32)

0 commit comments

Comments
 (0)