Wednesday, January 30, 2013

Why a process's memory usage won't decrease after being freed?

I'm using OS X and use Activity Monitor to check the memory usage of my program. However, this may fool people to think that their programs have memory leakages.

Let's check this example.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct list {
  char data[1024];
  struct list *next;
};

int main(int argc, char *argv[])
{
  sleep(5);

  /* Consume some memory  */
  struct list *head = malloc(sizeof(struct list));
  
  int i = 300;
  struct list *p = head;
  while (i-->0) {
    p->next = malloc(sizeof(struct list));
    p = p->next;
  }
 
  printf("Consumed a lot memory. Wait 5s to free them\n");

  sleep(5);

  i = 300;
  while (i-->0) {
    p = head->next;
    free(head);
    head = p;
  }

  printf("freed, wait 10s to exit\n");
  sleep(10);

  return 0;
}

Open your Activity Monitor and filter out your program, you will see that at first stage, the program costs about 150kb, then about 500kb after five seconds. After freeing the memory, you can see that the program still costs 500kb.

Why is this happening?

Put simply, the memory malloc'ed is granted to your process and won't return to OS immediately after you call free. The freed memory can be used later by the process.

A little more detail: http://stackoverflow.com/questions/447899/why-does-my-c-program-not-free-memory-as-it-should/447932#447932

Thursday, January 24, 2013

Make shell script(PuTTY plink or SSH) a daemon that never dies! (using Ubuntu Upstart)

I have a script that creates a SSH Tunnel using PuTTY plink. Problem is that it dies sometimes. I have a old laptop running Ubuntu Server in my home. Also I want that script to be executed when the server starts up and automatically respawns another instance if it dies.

There are some old fashioned ways to do it which I won't detail. I'm going to introduce you the modern way using Upstart.

My first config is this one. Located at "/etc/init/plink.conf".

start on runlevel [2345] or net-device-up IFACE!=lo
stop on runlevel [!2345]

respawn

exec plink -D 7070 -N -pw mypassword user@host

However, this just won't work. I checked its status using "sudo status plink", only to find its state is "stopped/waiting". I also use "ps -ejH" to debug and find its pid changes every few seconds.Why is this happening?

Then I came across this page: http://www.greenend.org.uk/rjk/sshfwd/. It enlightens me to find out what plink says.

I created a script like this:

# redirect stderr to file 1
exec > /home/clear/ssh-forwarding.log 2>&1

exec plink -D 7070 -N -pw mypassword user@host
When I cat /home/clear/ssh-forwarding.log, then I found this:
The authenticity of host 'host (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is 62:af:59:cb:ef:89:b7:45:bc:56:a1:96:59:56:49:2f.
Are you sure you want to continue connecting (yes/no)? 

Then I realized that Upstart keeps respawning plink because it timeouts waiting for my answer.

The solution is simple.
1. su to root
2. issue the plink command and answer yes to trust the host.

The final plink.conf:

start on runlevel [2345] or net-device-up IFACE!=lo
stop on runlevel [!2345]
 
respawn
respawn limit 5 60 # respawn max 5 times in 60 seconds

script
 set -e
 exec > /home/clear/ssh-forwarding.log 2>&1
 exec plink -D 7070 -N -pw mypassword user@host
end script
Finally, reboot. I happily find that plink is running now!

Hello, world!

I started several blogs last few years. However, I kept it privately and locally at last, because its naiveness and the possibility to leak my personal information.

I decided to start this blog on blogger mainly because I want to contribute to the general accessible knowledge.

This blog mainly focuses on Unix and C related topics I came across.