@@ -17,6 +17,7 @@ import (
17
17
"strconv"
18
18
"strings"
19
19
"sync"
20
+ "sync/atomic"
20
21
"syscall"
21
22
"testing"
22
23
"unsafe"
@@ -654,3 +655,63 @@ func TestAllThreadsSyscallBlockedSyscall(t *testing.T) {
654
655
wr .Close ()
655
656
wg .Wait ()
656
657
}
658
+
659
+ //go:linkname syscall_prlimit syscall.prlimit
660
+ func syscall_prlimit (pid , resource int , newlimit , old * syscall.Rlimit ) error
661
+
662
+ //go:linkname syscall_origRlimitNofile syscall.origRlimitNofile
663
+ var syscall_origRlimitNofile atomic.Pointer [syscall.Rlimit ]
664
+
665
+ func TestPrlimitSelf (t * testing.T ) {
666
+ syscall_origRlimitNofile .Store (& syscall.Rlimit {
667
+ Cur : 1024 ,
668
+ Max : 65536 ,
669
+ })
670
+
671
+ // Get the current nofile limit
672
+ var lim syscall.Rlimit
673
+ if err := syscall .Getrlimit (syscall .RLIMIT_NOFILE , & lim ); err != nil {
674
+ t .Fatalf ("Failed to get the current nofile limit: %v" , err )
675
+ }
676
+ // Set current process's nofile limit through prlimit
677
+ if err := syscall_prlimit (0 , syscall .RLIMIT_NOFILE , & lim , nil ); err != nil {
678
+ t .Fatalf ("Prlimit self failed: %v" , err )
679
+ }
680
+
681
+ rlimLater := syscall_origRlimitNofile .Load ()
682
+ if rlimLater != nil {
683
+ t .Fatalf ("origRlimitNofile expected to be nil, but got %v" , rlimLater )
684
+ }
685
+ }
686
+
687
+ func TestPrlimitOtherProcess (t * testing.T ) {
688
+ syscall_origRlimitNofile .Store (& syscall.Rlimit {
689
+ Cur : 1024 ,
690
+ Max : 65536 ,
691
+ })
692
+ rlimOrig := syscall_origRlimitNofile .Load ()
693
+
694
+ // Get the current nofile limit
695
+ var lim syscall.Rlimit
696
+ if err := syscall .Getrlimit (syscall .RLIMIT_NOFILE , & lim ); err != nil {
697
+ t .Fatalf ("Failed to get the current nofile limit: %v" , err )
698
+ }
699
+
700
+ // Start a child process firstly,
701
+ // so we can use Prlimit to set it's nofile limit.
702
+ cmd := exec .Command ("sleep" , "infinity" )
703
+ cmd .Start ()
704
+
705
+ // Set child process's nofile rlimit through prlimit
706
+ if err := syscall_prlimit (cmd .Process .Pid , syscall .RLIMIT_NOFILE , & lim , nil ); err != nil {
707
+ t .Fatalf ("Prlimit(%d) failed: %v" , cmd .Process .Pid , err )
708
+ }
709
+
710
+ cmd .Process .Kill ()
711
+ cmd .Process .Wait ()
712
+
713
+ rlimLater := syscall_origRlimitNofile .Load ()
714
+ if rlimLater != rlimOrig {
715
+ t .Fatalf ("origRlimitNofile expected to be %v, but got %v" , rlimOrig , rlimLater )
716
+ }
717
+ }
0 commit comments