GP2X Shell Scripts Leak Memory


RiX0R

Idler-Inside
Joined
Sep 20, 2005
Messages
294
Website
rix0r.nl
This may be relevant to shell script writers:

Shell scripts as they are usually written now leak memory!

I'm referring to the scripts that end with:
Code:
#!/bin/sh
...
cd /usr/gp2xmenu
./gp2xmenu

What happens here is that the gp2x menu is launched in a subprocess. The current process (the shell executing the script) will remain in memory, waiting for the menu to terminate. This will never happen, so the shell process will remain in memory indefinitely, consuming memory (thankfully not CPU cycles).

So every time you run a script, an instance of the shell remains in memory.

Schematically:

shot-20060119.122344.gif


Now, in all praticality, this may not be much of an issue. I've tested it on my machines, and it took about 200 scripts to consume enough memory that my menu wouldn't work anymore. Considering the average uptime of a GP2X, it will probably never occur that the memory is filled up in a harmful way, unless of course you're running an application that requires every last KB of memory.

I would estimate that each instance takes about 150~160KB of memory, so if you say that an average game would require about 15MB (I have no idea of realistic amounts, but this seems ample), it would require (32 - 15) / 0.16 = 106 leaking shells before the game would start to notice -- a few less if you count the memory taken up by the kernel.

As I said, this is mostly an issue of elegance, but it bears keeping in mind... seeing how the fix is very simple:

Code:
#!/bin/sh
...
cd /usr/gp2x
exec ./gp2xmenu

By using exec, the gp2xmenu process will now replace the shell, and the memory is returned to the system.
 
I'm not sure the script process will stay in memory for ever. Sure it wait for the menu process to end, but if the menu as to be launched after any programs, isn't it because it dies at program launch ? If I'm right, the script process will stay alive until another program is laucnhed.
 
I'm not sure the script process will stay in memory for ever. Sure it wait for the menu process to end, but if the menu as to be launched after any programs, isn't it because it dies at program launch ? If I'm right, the script process will stay alive until another program is laucnhed.

No, it really does stay in memory forever. I wrote a note to Brendan, who did the excellent port of Python and PyGame to the GP2X, asking him to add the 'exec' suggestion to his docs. The thing is that gp2xmenu probably does an 'exec' itself when launching -- which means that the launched program replaces the current process, so from the calling shell's perspective, nothing died. So now the first calling shell is waiting for the launched program to finiish. Lather, rinse, repeat.

I've watched it happen by being logged into a bash shell on the GP2X via the USB-serial. The shell processes really do stack up.
 
Last edited by a moderator:
I changed my /etc/profile to end like this:

while true ; do
cd /usr/gp2x
./gp2xmenu
done

This way, programs and shell scripts can exit normally (return or exit(0)). IMHO this is the way it should have been in the first place: expecting programs to exit by calling the system menu is just silly.
 
while true ; do
cd /usr/gp2x; ./gp2xmenu
done
This way, programs and shell scripts can exit normally (return or exit(0)).
That's a really cool idea.

IMHO this is the way it should have been in the first place: expecting programs to exit by calling the system menu is just silly.
I agree that it's silly, but your method keeps one shell running at all times, right? What are the memory implications of that? (That could be why it's not the default.)
 
Last edited by a moderator:
GregAllen posted on Feb 7 2006 at 01:34 PM said:
while true ; do
cd /usr/gp2x; ./gp2xmenu
done
This way, programs and shell scripts can exit normally (return or exit(0)).
That's a really cool idea.

IMHO this is the way it should have been in the first place: expecting programs to exit by calling the system menu is just silly.
I agree that it's silly, but your method keeps one shell running at all times, right? What are the memory implications of that? (That could be why it's not the default.)

The orginal method is also keeping the shell: profile ends with "cd /usr/gp2x; ./gp2xmenu" without the while loop. What's happening is that the shell calls gp2xmenu and waits for the exit; then gp2xmenu execs a game (the game replaces gp2xmenu). When the game proces (replacing gp2xmenu) exits normally, it returns to the profile script, which ends at this point and prompts the user in the console (which we can't see in the GP2X without a serial cable).

This while loop plus the usb-serial module is a great combo!
 
Last edited by a moderator:
Back
Top