@@ -83,6 +83,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
8383 struct kinfo_proc * buf = NULL ;
8484 int name [] = { CTL_KERN , KERN_PROC , KERN_PROC_PROC , 0 };
8585 size_t length = 0 ;
86+ size_t max_length = 12 * 1024 * 1024 ; // 12MB
8687
8788 assert (procList != NULL );
8889 assert (* procList == NULL );
@@ -95,20 +96,36 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
9596 return 1 ;
9697 }
9798
98- // Allocate an appropriately sized buffer based on the results
99- // from the previous call.
100- buf = malloc (length );
101- if (buf == NULL ) {
102- PyErr_NoMemory ();
103- return 1 ;
104- }
99+ while (1 ) {
100+ // Allocate an appropriately sized buffer based on the results
101+ // from the previous call.
102+ buf = malloc (length );
103+ if (buf == NULL ) {
104+ PyErr_NoMemory ();
105+ return 1 ;
106+ }
105107
106- // Call sysctl again with the new buffer.
107- err = sysctl (name , 3 , buf , & length , NULL , 0 );
108- if (err == -1 ) {
109- PyErr_SetFromOSErrnoWithSyscall ("sysctl" );
110- free (buf );
111- return 1 ;
108+ // Call sysctl again with the new buffer.
109+ err = sysctl (name , 3 , buf , & length , NULL , 0 );
110+ if (err == -1 ) {
111+ free (buf );
112+ if (errno == ENOMEM ) {
113+ // Sometimes the first sysctl() suggested size is not enough,
114+ // so we dynamically increase it until it's big enough :
115+ // https://github.com/giampaolo/psutil/issues/2093
116+ psutil_debug ("errno=ENOMEM, length=%zu; retrying" , length );
117+ length *= 2 ;
118+ if (length < max_length ) {
119+ continue ;
120+ }
121+ }
122+
123+ PyErr_SetFromOSErrnoWithSyscall ("sysctl()" );
124+ return 1 ;
125+ }
126+ else {
127+ break ;
128+ }
112129 }
113130
114131 * procList = buf ;
0 commit comments