Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

13 April, 2011

dlopen(0, RTLD_NOW | RTLD_GLOBAL) doesn't work?

You need to compile the binary with -rdynamic flag to expose all the symbols in the  binary, otherwise, it is highly possible that the symbol could not be found.

16 March, 2011

Copy backtrace log to file

According to this link:

gdb -batch-silent -ex "run" -ex "set logging overwrite on" -ex "set logging file gdb.bt" -ex "set logging on" -ex "set pagination off" -ex "handle SIG33 pass nostop noprint" -ex "echo backtrace:\n" -ex "backtrace full" -ex "echo \n\nregisters:\n" -ex "info registers" -ex "echo \n\ncurrent instructions:\n" -ex "x/16i \$pc" -ex "echo \n\nthreads backtrace:\n" -ex "thread apply all backtrace" -ex "set logging off" -ex "quit" --args'

you can use those arguments to dump your huge bt log into a file!

06 January, 2011

Get all network interfaces using SIOCGIFCONF

Use ioctl with SIOCGIFCONF can get the names of every network interface in your machine. It should be faster than parsing the output of "ifconfig" command.

21 June, 2010

Boost: build command

bjam --build-dir=/tmp/boost_build --toolset=gcc --build-type=complete address-model=64 --stagedir=stage64 stage

bjam --build-dir=/tmp/boost_build --toolset=gcc --build-type=complete architecture=x86 address-model=32 --stagedir=stage32 stage

19 March, 2010

Do not use exit() in your C++ daemon

Do not use exit() in your C++ daemon program!!! The destructor of global variable will be invoke, it might not what you desire.

The scenario is when you try to daemonize your program, you will call exit(0) when fork()!=0. If you did that, terrible thing happens, all destructor of your global variable will be invoke. For example, the global object to do log.

To avoid this situation, use _exit() instead of exit(). The only difference between those two functions is _exit() will NOT invoke the functions register by atexit(). In the other word, the destructor will not be invoke.

Here is my C++ daemonize function:
static void daemonize()
{
if( SIG_ERR == signal(SIGTTOU, SIG_IGN) ||
SIG_ERR == signal(SIGTTIN, SIG_IGN) ||
SIG_ERR == signal(SIGTSTP, SIG_IGN) )
exit(EXIT_FAILURE);

if (0 != fork()) _exit(0);

if (-1 == setsid()) exit(EXIT_FAILURE);

umask(0);
if (0 != chdir("/")) exit(EXIT_FAILURE);

close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}

12 March, 2010

[PHP][Lighttpd] Using IE6 to download file through SSL connection

Using IE6 to download file from lighttpd server using HTTPS connection is troublesome.
In this article:
Every configuration in it is really helpful, however, I still cannot solve the problem!

What I want to do is using PHP to read the file content and echo back to my client. This approach seems find when working with FF, Chrome, Opera, IE7 and IE8. But the wacky IE6 doesn't take that way. After applying the configs mentions in the article, there is a final magic config. that is :
ini_set('zlib.output_compression', 'Off');

It seems like that the zlib plugin will send some secrete headers back to browser to ruin the cache control header sent by my php script.. Turn it off and everything goes perfect!!!

In the end, I have to say that I HATE IE6!!! Why do we still need to support this buggy old fashion browser???

22 February, 2010

About the zombie fastcgi process

I was WRONG in the previous post, sometime we will see some zombie fastcgi process running, but that is perfectly OK because when lighttpd receive the new request, it will invoke waitpid and then the zombie process will be gone! The chance of invoking waitpid on the zombie process depends on the amount of max-worker of lighttpd, but it will eventually be invoke by the parent process. It is just the matter of time :)


06 February, 2010

Lighttpd: zombie fastcgi process

When lighttpd is starting, the mod_fastcgi plugin will fork every fastcgi it needs depending on the configuration. If fastcgi process terminate normally while lighttpd is still running, it seems alright at the beginning. However, if we encounter huge traffic and the process will terminate after handling a single request (with a reasonable excuse), the terminated fastcgi process sometimes become a zombie process! It is due to that the mod_fastcgi is too slow to invoke waitpid() function, when it get there, the processes are already gone. As you knew, a forked process without waitpid() in parent process will become a zombie process. This is the reason for getting a bunch of zombie running in my box.

Many tricks can prevent zombie process. According to my previous post, lighttpd already use the fork twice trick to prevent it. Unfortunately, they did something wrong.
In Bug #2144, some people observed the same situation. To solve this problem, I dig into the source code and found out the root cause.

According to my response to Bug #2144:
"
I encounter the same situation when I running my fastcgi program.

This problem is due to that we daemonize the lighttpd AFTER we initialize plugins. Therefore, the cgi/fcgi processes forked by mod_cgi/mod_fastcgi are still possible to become zombie processes.

Beside the order of invoking daemonize function in server.c, we also forget to ignore SIG_CHLD signal after the first fork, and it is the reason why the "fork twice" trick did not work.

The patch is for lighttpd-1.4.25, I did the following changes:
1. Invoke daemonize() before invoking plugins_call_init(srv).
2. Ignore SIG_CHLD after the first fork().
2. Do not handle SIG_CHLD signal after daemonize lighttpd.

"

I hope my patch can solve this issue once and for all. :D

05 February, 2010

Why fork twice?

When I were tracing the source code of lighttpd. I found out the daemonize function in server.c is quite interesting, it make itself become a daemon but it invoke fork() twice!

It seems like that there is no difference between forking once and forking twice, however, I accident found this article: http://hi.baidu.com/22000254/blog/item/9c2a01860d66713666096e38.html

The reason to fork twice is to prevent create zombie process! I never think of that before.


11 December, 2009

The fastest way to get time in millisecond on linux

"gettimeofday()" is a great function to get time in millisecond.

Sample usage:
struct timeval start, end;
gettimeofday(&start, NULL);
usleep(2000);
gettimeofday(&end, NULL);

printf("%ld milliseconds\n", ((end.tv_sec-start.tv_sec) * 1000 + (end.tv_usec-start.tv_usec)/1000.0));

Moreover, we can even speed up this function!
According to this post, we can enable Virtual Dynamic Shared Object to speed things up.
# echo 2 > /proc/sys/kernel/vsyscall64


25 November, 2009

FastCGI: non-blocking FCGI_Accept_r

1. FCGX_InitRequest(&request, 0, FCGI_FAIL_ACCEPT_ON_INTR)
2.
int flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NONBLOCK);
3. sigaction


"We intentionally try to set the SA_RESTART flag for all signals other than SIGALRM, so that any system call interrupted by these other signals is automatically restarted. The reason we don't want SIGALRM restarted is to allow us to set a timeout for I/O operations."

06 November, 2009

Vim: edit makefile

use "set noexpandtab" and set softtabstop to zero before editing your makefile.