5 #include <sys/resource.h>
7 #include <sys/sysctl.h>
9 #include <darwintest.h>
11 #define FILE_LIMIT 100
15 * (1) the maximum number of fds allowed open per process
16 * implemented by the kernel matches what sysconf expects:
18 * 64 bit: RLIM_INFINITY
19 * (2) fopen does not fail when NOFILE is unlimited.
21 T_DECL(stdio_PR_63187147_SC_STREAM_MAX
, "_SC_STREAM_MAX test")
24 long stream_max
, saved_stream_max
, open_count
, i
;
25 int maxfilesperproc
, err
;
26 size_t maxfilesperproc_size
= sizeof(maxfilesperproc
);
28 const char *filename
= "fopen_test";
32 saved_stream_max
= sysconf(_SC_STREAM_MAX
);
33 T_LOG("Initial stream_max %ld", saved_stream_max
);
35 /* Decide the maximum number of fds allowed by the kernel */
36 err
= sysctlbyname("kern.maxfilesperproc", &maxfilesperproc
, &maxfilesperproc_size
, NULL
, 0);
37 T_EXPECT_POSIX_SUCCESS(err
, "sysctlbyname(\"kern.maxfilesperproc\") returned %d", err
);
38 T_LOG("kern.maxfilesperproc %d", maxfilesperproc
);
41 * Raise RLIMIT_NOFILE to RLIM_INFINITY, note that this does NOT update
42 * __stream_max in findfp.c
44 err
= getrlimit(RLIMIT_NOFILE
, &rlim
);
45 T_EXPECT_POSIX_SUCCESS(err
, "getrlimit(RLIMIT_NOFILE)");
46 T_LOG("Initial RLIMIT_NOFILE rlim.cur: 0x%llx", rlim
.rlim_cur
);
47 rlim
.rlim_cur
= RLIM_INFINITY
;
48 err
= setrlimit(RLIMIT_NOFILE
, &rlim
);
49 T_EXPECT_POSIX_SUCCESS(err
, "setrlimit(RLIMIT_NOFILE) to RLIM_INFINITY");
50 err
= getrlimit(RLIMIT_NOFILE
, &rlim
);
51 T_EXPECT_POSIX_SUCCESS(err
, "New RLIMIT_NOFILE rlim_cur: 0x%llx", rlim
.rlim_cur
);
56 * Test 1 (sysconf with _SC_STREAM_MAX): the largest value sysconf
57 * returns for _SC_STREAM_MAX is OPEN_MAX (32 bit) or
58 * RLIM_INFINITY (64 bit)
60 stream_max
= sysconf(_SC_STREAM_MAX
);
61 T_EXPECT_NE_LONG((long)-1, stream_max
, "stream_max %ld", stream_max
);
63 T_EXPECT_EQ((long)RLIM_INFINITY
, stream_max
, "sysconf returned 0x%lx", stream_max
);
65 T_EXPECT_EQ((long)OPEN_MAX
, stream_max
, "sysconf returned 0x%lx", stream_max
);
69 * Test 2 (__stream_max in findfp.c): exercise __sfp by calling fopen
70 * saved_stream_max + 1 times. Note that we call fopen() up to
71 * maxfilesperproc times in case fopen() goes nuts.
73 fp
= malloc(sizeof(FILE *) * (size_t)maxfilesperproc
);
74 T_EXPECT_NOTNULL(fp
, "Allocated %d FILE pointers", maxfilesperproc
);
75 for (i
= 0; i
< saved_stream_max
+ 1 && i
< maxfilesperproc
; i
++) {
76 if (i
== saved_stream_max
) {
77 T_LOG("The very next fopen should trigger __sfp to update __stream_max and fopen shouldn't fail ");
79 fp
[i
] = fopen(filename
, "r");
80 T_QUIET
; T_EXPECT_NOTNULL(fp
, "%ld: fopen(%s, \"r\")", i
, filename
);
84 for (i
= 0; i
< open_count
; i
++) {
89 T_LOG("saved_stream_max %ld stream_max %ld fopen %ld files", saved_stream_max
, stream_max
, open_count
);
92 T_DECL(stdio_PR_22813396
, "STREAM_MAX is affected by changes to RLIMIT_NOFILE")
94 struct rlimit theLimit
;
95 getrlimit( RLIMIT_NOFILE
, &theLimit
);
96 theLimit
.rlim_cur
= FILE_LIMIT
;
97 setrlimit( RLIMIT_NOFILE
, &theLimit
);
99 long stream_max
= sysconf(_SC_STREAM_MAX
);
100 T_EXPECT_EQ_LONG(stream_max
, (long)FILE_LIMIT
, "stream_max = FILE_LIMIT");
103 for(int i
= 3; i
< stream_max
; i
++) {
104 if((f
= fdopen(0, "r")) == NULL
) {
105 T_FAIL("Failed after %d streams", i
);
110 T_EXPECT_NULL(f
, "fdopen fail after stream_max streams");
112 theLimit
.rlim_cur
= FILE_LIMIT
+ 1;
113 setrlimit( RLIMIT_NOFILE
, &theLimit
);
116 T_EXPECT_NOTNULL(f
, "fdopen succeed after RLIMIT_NOFILE increased");
119 T_DECL(stdio_PR_22813396_close
, "STREAM_MAX is enforced properly after fclose")
121 struct rlimit theLimit
;
122 getrlimit( RLIMIT_NOFILE
, &theLimit
);
123 theLimit
.rlim_cur
= FILE_LIMIT
;
124 setrlimit( RLIMIT_NOFILE
, &theLimit
);
126 long stream_max
= sysconf(_SC_STREAM_MAX
);
127 T_EXPECT_EQ_LONG(stream_max
, (long)FILE_LIMIT
, "stream_max = FILE_LIMIT");
130 for(int i
= 3; i
< stream_max
- 1; i
++) {
131 if((f
= fdopen(0, "r")) == NULL
) {
132 T_FAIL("Failed after %d streams", i
);
136 // the last stream is for dup(0), it needs to be fclose'd
138 T_EXPECT_NOTNULL(dupf
= fdopen(dup(0), "r"), NULL
);
140 T_EXPECT_NULL(f
= fdopen(0, "r"), "fdopen fail after stream_max streams");
142 T_EXPECT_POSIX_ZERO(fclose(dupf
), "fclose succeeds");
145 T_WITH_ERRNO
; T_EXPECT_NOTNULL(f
, "fdopen succeed after fclose");