Tag Archives: Linux debugging

Popen error: cannot allocate memory [How to Solve]

 

Foreword

This is a bug found in the actual project. After the device runs for a period of time, an error is reported: Poppen error: cannot allocate memory. Operating platform: Xintang nuc970, memory 64M, Linux kernel version: 3.10.108 +.


1. Popen introduction

The Popen function creates a child process to execute Shell, and shell A sub process is created to execute commands. From the practice process, it can be seen that after the process allocates memory and fills the process stack space, these functions fail to execute and return enomem error code cannot allocate memory. As long as the space is not released, the execution fails all the time

2. Cause analysis of Popen error

Here is a test program to reproduce the problem: the main thread malloc applies for heap space and fills the stack space of the process; Another thread performs the Popen operation. The result is that when the routine thread executes Popen, it always reports a Popen error: cannot allocate memory error until the main thread executes the free operation.

1. System memory of the device

2. Run the test program./test  , Max statck size is just 8m

3. Results: when the process is running, an error is reported when the heap space exceeds 8m, but in fact, the memory in the system is still sufficient, with more than 37m.

4. Once the space requested by malloc is released, it will return to normal immediately

5. Test program source code

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/sysinfo.h>

#define SIZE (1024*1024*1)
#define MEM_SIZE (45)

void *routine(void *arg)
{
	struct sysinfo info;
	
	while(1)
	{		
		sysinfo(&info);
		printf("freeram = %ld\n",info.freeram);
		
		FILE* fp = popen("cat /sys/class/net/eth0/carrier", "r");
		if(fp == NULL)
		{
			printf("popen error:%s\n", strerror(errno));
			sleep(1);
			continue;
		}
		
		char  buffer[1024];
		int   bytes_read = fread(buffer, 1, sizeof(buffer), fp);
		pclose(fp);

		printf("popen ok %2x\n",buffer[0]);			
		sleep(1);
		
	}
}

int main(int argc, char **argv)
{
		
	pthread_t tid;
	pthread_create(&tid, NULL, routine, NULL);
	

	unsigned int *p = (unsigned int *)malloc(1024 * 1024 * MEM_SIZE);
	printf("malloc buffer: %p\n", p);

	for (int i = 0; i < 1024 * 1024 * (MEM_SIZE/sizeof(int)); i++) 
	{
		p[i] = 123;
		if ((i & 0xFFFFF) == 0) 
		{
			printf("%dMB written\n", i >> 18);
			sleep(1);
			//usleep(100000);
		}

	}

	
	while(1)
	{
		sleep(20);
		if(p)
		{
			printf("free mem\n"); //The popen call is normal after the memory is released
			free(p);
			p = NULL;
		}
	}
	
	return 0;
}

Summary

The system overhead of functions such as Popen is very high. When the process memory is tight, it is easy to make mistakes. If the requested memory space is not released in time, the execution fails all the time.