iT邦幫忙

DAY 10
2

emacs的30天學習筆記系列 第 10

emacs 做中學第十天:GDB tarace不進去的地方,一個讓人意猶未盡的狀況

早上5點不到爬起床,現在8點多。

在整理下一個階段的內容,CGI/FASTCGI, 這些早期的老掉牙技術,因為當紅的web framework ROR (RUBY ON RAILS)採用FASTCGI,又重新讓人注意。

在mini web server中,有一個德國人,http://towiski.de/software.html寫的支援CGI 的程式,引起我的注意。

有了之前累積的經驗,應該如法泡製,而且他的寫法和獵豹某些結構上,命名方式,有些異曲同工的地方。3小時後,筆者發現,看code,和trace code,不一樣。
web server 基本上都有一個主迴圈hold住,在listen 來自browser的requset,
以 mattows為例(下載網址:http://towiski.de/binaries/mattows-1.8.tar.bz2)
是這樣寫:

	while(1) {
		int pid;
		socklen_t peerlen=sizeof(peer);
		
		mywarn("Waiting for connections on port %d\n",ntohs(port));
		as = accept(sock,(struct sockaddr*)&peer,&peerlen);
		if(-1 == as) {
			if(EINTR != errno)
				mywarn("accept: %s\n",strerror(errno));
			continue;
		}
		switch(pid = fork()) {
			case -1 :
				mywarn("error forking connection handler: %s\n",strerror(errno));
				break;
			case 0 :
				close(sock);
				mywarn("Accepted connection from %s:%d\n",
						inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
				exit(handle_connection(as,&peer));
			default :
				close(as);
		}
	}

看得出來,handle_connection是我們關注的點。看了code,也如我們相像的。 把中斷點,下在這裏。b handle_connection
做了N次,每次都過站不停

我想,怪怪的,那我停在
switch(pid = fork(),
我發現一個更奇異的現象,
它每次的跑法,

		switch(pid = fork()) {
			case -1 :
				mywarn("error forking connection handler: %s\n",strerror(errno));
				break;
			case 0 :
				close(sock);
				mywarn("Accepted connection from %s:%d\n",
						inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
				exit(handle_connection(as,&peer));
			default :
				close(as);
		}

都直接跑到 default:

可是從它show在console的訊息,它明明有跑選項case 0 :,這個case也一直過站不停。

但是雖然我的C語言再不行,但是也有看過邦友在LINUX相關的分享,
行程的ID, 要0的機會有可能嗎??可能是系統初始化的行程嗎?以我的ubuntu為例,

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 2528 1268 ? Ss 14:49 0:01 /sbin/init

最小到1,沒有0,那這個德國高人,寫0,顯然是另有所指,google 一下
pid 0,有人說用ps -ef,在我的ubuntu上。也沒有0.

一般fork()出來行程,以筆者的ubuntu為例,也是
27xx,或28xx,一般常識判斷,得到0的機會不大,得到-1,還比較大。

玄機往往就在這裏,心理同時也有一些CALL BACK FUNCTION, 或是hook 想法,
這些讓程式的跑法,不如預期的程式寫法。

先從另一個線索,
以mattows SHOW在console的訊息,

mattows [2771]: Waiting for connections on port 8000
mattows [2886]: Accepted connection from 127.0.0.1:51639
mattows [2886]: Executing hellow.cgi
mattows [2771]: Child process 2886 exited with status 0

一個requset的處理,它會秀出4段log。
Child process 去 grep source ,發現

/* clean up dead children */
static void child_reaper(int sig)
{
	int status, pid;

	while(0 < (pid = waitpid(-1,&status,WNOHANG)))
		mywarn("Child process %d exited with status %d\n",pid,status);
}

這個function下中斷點,可以停下來,
這個child_reaper
給了筆者下一個線索。

	struct sigaction sa = {
		.sa_handler = &child_reaper,
		.sa_flags = SA_NOCLDSTOP
	};
	sigaction(SIGCHLD,&sa,NULL);

sigaction是一個
The sigaction() system call is used to change the action taken by a process on receipt of a specific signal.
來源自http://linux.die.net/man/2/sigaction
這個系統呼叫,可以用來改變一個傳回的指定信號的動作。
以本例來說,
接收到SIGCHLD(子行程建立後),去執行child_reaper,檢查子行程是否還殘留。

學到一個系統呼叫的用法,雖然仍沒有找出無法trace的原因。

寫到這裏,筆者突然發現,似乎誤解了fork()回傳值的意思,
再google一下fork(), 中文資料很多。

返回值:
-1 : 失敗。
0 : 子程序。

0 : 將子程序的process id傳回給父程序。

所以 case 0,是對的。之前以為只傳回process id或失敗,原來真的有傳回0

那為什麼不進來 case 0??

看來筆者要使出終極絕招---->寫信給原作者,雖然不會德文(網址是de),看他
網站內容,程式註解都用英文,用英文寫,應該可以吧,不知道他有沒有提供
technology support?

結論:
隨著對system call的理解,可以了解,不同人使用方式不一樣,如cheetah的作者就沒用sigaction。

網際網路google的大量訊息泛濫,帶來了程式人員的好處,
尤其是應用程式的code,大多可以google到sample code。
通常google 來的code,不太關底層架構,湊和著,通常都可以用,
但是code拿到了,trace不出想要的方向,這時,google到原作者的網站,
發個mail,有時也是不錯的方法 。

等待的同時,仍然可以繼續進行專案的其他部分,IT從業人員,常常是有超的求知慾,不解出來就不眠不休,這時候,如果專案蠻大的話,就要暫時放下,
先完成專案的其他部分,大家都有類似的經驗,有時搞了4/5個小時沒解的bug,
出去跑兩圈,洗個澡,回頭看一下,改一下,就解了。這時反而會回頭咒罵幹嘛多花那4/5個小時。

PS:在看其他邦友分享的文章時,意外發現,C語言之父走了,
一直以為瑞奇先生,和SQL發明者,是不少IT從業人員的衣食父母,
因為很多人很靠此維生,甚至有不錯的收入,哈佛某教授好像有講過,
利害的人是創業自己當老闆,差一點的是被人找去當管理者,更高明的是
自己無中生有一個產業,瑞奇先生發明C語言又共同發明UNIX, 是兩倍的高明。


上一篇
emacs 做中學第九天:學然後知不足,用然後知不好用
下一篇
emacs 做中學第十一天: Synaptic套件庫的更新
系列文
emacs的30天學習筆記38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
chiounan
iT邦研究生 1 級 ‧ 2011-10-17 10:03:19

筆記用功,用功。

我要留言

立即登入留言