<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[前些年在sina 企业mail的rpc在freebsd老是倒，在网上看到一个哥们说烂]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sun, 04 Oct 2009 04:43:50 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	北京 sina 企业邮箱，老是需要重启（已经替换php掉了，rpc在salary上运行很正常，但是在freebsd上就有僵尸和无缘无故死掉的可能），可能是超时没有人连接：<br/>转下面一个网路上哥们的文章，但是他没有提出解决方案，呵呵，等于没有说：<br/>亲爱的，稍微改进下你的程序吧，这不费多大事儿。<br/><br/>我在一个多线程的corba程序的多个worker线程中调用了sun rpc的clnt_create函数。然后我的程序偶尔会core dump【http://blog.5ifd.com/post/2023/】.查了下，backtrace如下：<br/><br/>#0&nbsp;&nbsp;0×84c7f82a in fclose (fp=0×0) at /usr/src/lib/libc/stdio/fclose.c:56<br/><br/>#1&nbsp;&nbsp;0×84c4b0a2 in endnetconfig (handlep=0×86e0420) at /usr/src/lib/libc/rpc/getnetconfig.c:394<br/><br/>#2&nbsp;&nbsp;0×84c40cc5 in __rpc_endconf (vhandle=0×86e0410) at /usr/src/lib/libc/rpc/rpc_generic.c:441<br/><br/>#3&nbsp;&nbsp;0×84c327eb in clnt_create_timed (hostname=0×80977d8 “127.0.0.1″, prog=931729681, vers=1,<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;netclass=0×80977d4 “tcp”, tp=0×0) at /usr/src/lib/libc/rpc/clnt_generic.c:271<br/><br/>#4&nbsp;&nbsp;0×84c3264d in clnt_create (hostname=0×80977d8 “127.0.0.1″, prog=931729681, vers=1,<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;nettype=0×80977d4 “tcp”) at /usr/src/lib/libc/rpc/clnt_generic.c:186<br/><br/>．．．　后面的我略了。<br/><br/>然后我打开netnetconfig.c看了下<br/><br/>endnetconfig中调用了fclose函数关闭一个叫做nc_file的file handle。而这个file handle是一个全局静态变量。<br/><br/>static FILE *nc_file; <br/><br/>然而在使用这个变量的时候，完全没有加锁。<br/><br/>如<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;ni.ref++;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if ((nc_file != NULL) &#124;&#124; (nc_file = fopen(NETCONFIG, “r”)) != NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc_vars->valid = NC_VALID;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc_vars->flag = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc_vars->nc_configs = ni.head;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ((void *)nc_vars);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;ni.ref–;<br/><br/>其实问题很简单，<br/><br/>static pthread_mutex_t nc_file_lock = PTHREAD_MUTEX_INITIALIZER;<br/><br/>定义一个mutex,然后在恰当的时候获取、释放锁就行了。<br/><br/>亲爱的，稍微改进下你的程序吧，这不费多大事儿。<br/><br/>—————-分隔线—————————<br/><br/>14:22 2007-12-11<br/><br/>光说不干是可耻的。做了个patch,如下：<br/><br/>— src/lib/libc/rpc/getnetconfig.c.orig Tue Dec 11 13:45:32 2007<br/><br/>+++ src/lib/libc/rpc/getnetconfig.c Tue Dec 11 14:11:41 2007<br/><br/>@@ -131,7 +131,10 @@ static struct netconfig *dup_ncp(struct<br/><br/> <br/><br/> <br/><br/> static FILE *nc_file;&nbsp;&nbsp;/* for netconfig db */<br/><br/>+static pthread_mutex_t nc_file_lock = PTHREAD_MUTEX_INITIALIZER;<br/><br/> static struct netconfig_info ni = &#123; 0, 0, NULL, NULL&#125;;<br/><br/>+/* should not acquire it after acquired a nc_file_lock */ static<br/><br/>+pthread_mutex_t ni_lock = PTHREAD_MUTEX_INITIALIZER;<br/><br/> <br/><br/> #define MAXNETCONFIGLINE&nbsp;&nbsp;&nbsp;&nbsp;1000<br/><br/> <br/><br/>@@ -205,14 +208,23 @@ setnetconfig()<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* For multiple calls, i.e. nc_file is not NULL, we just return the<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* handle without reopening the netconfig db.<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ni.ref++;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&ni_lock);<br/><br/>+<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if ((nc_file != NULL) &#124;&#124; (nc_file = fopen(NETCONFIG, “r”)) != NULL) &#123;<br/><br/>&nbsp;&nbsp;nc_vars->valid = NC_VALID;<br/><br/>&nbsp;&nbsp;nc_vars->flag = 0;<br/><br/>&nbsp;&nbsp;nc_vars->nc_configs = ni.head;<br/><br/>+ mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;return ((void *)nc_vars);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&nc_file_lock);<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ni.ref–;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&ni_lock);<br/><br/>+<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; nc_error = NC_NONETCONFIG;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; free(nc_vars);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; return (NULL);<br/><br/>@@ -235,15 +247,17 @@ void *handlep;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; char *stringp;&nbsp;&nbsp;/* tmp string pointer */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; struct netconfig_list *list;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; struct netconfig *np;<br/><br/>-<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;struct netconfig *result;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; /*<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Verify that handle is valid<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if (ncp == NULL &#124;&#124; nc_file == NULL) &#123;<br/><br/>&nbsp;&nbsp;nc_error = NC_NOTINIT;<br/><br/>+ mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;return (NULL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>-<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; switch (ncp->valid) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; case NC_VALID:<br/><br/>&nbsp;&nbsp;/*<br/><br/>@@ -256,7 +270,9 @@ void *handlep;<br/><br/>&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;if (ncp->flag == 0) &#123; /* first time */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ncp->flag = 1;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ncp->nc_configs = ni.head;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (ncp->nc_configs != NULL) /* entry already exist */<br/><br/>&nbsp;&nbsp; return(ncp->nc_configs->ncp);<br/><br/>&nbsp;&nbsp;&#125;<br/><br/>@@ -269,7 +285,12 @@ void *handlep;<br/><br/>&nbsp;&nbsp; * If we cannot find the entry in the list and is end of file,<br/><br/>&nbsp;&nbsp; * we give up.<br/><br/>&nbsp;&nbsp; */<br/><br/>- if (ni.eof == 1) return(NULL);<br/><br/>+ mutex_lock(&ni_lock);<br/><br/>+ if (ni.eof == 1) &#123;<br/><br/>+&nbsp;&nbsp; mutex_unlock(&ni_lock);<br/><br/>+&nbsp;&nbsp; return(NULL);<br/><br/>+ &#125;<br/><br/>+ mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp;break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; default:<br/><br/>&nbsp;&nbsp;nc_error = NC_NOTINIT;<br/><br/>@@ -290,14 +311,18 @@ void *handlep;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; /*<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* Read a line from netconfig file.<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; do &#123;<br/><br/>&nbsp;&nbsp;if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(stringp);<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp; mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ni.eof = 1;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&ni_lock);<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (NULL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125; while (*stringp == ‘#’);<br/><br/>-<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if (list == NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(stringp);<br/><br/>@@ -326,6 +351,7 @@ void *handlep;<br/><br/>&nbsp;&nbsp; * Reposition the current pointer of the handle to the last entry<br/><br/>&nbsp;&nbsp; * in the list.<br/><br/>&nbsp;&nbsp; */<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;if (ni.head == NULL) &#123; /* first entry */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ni.head = ni.tail = list;<br/><br/>&nbsp;&nbsp;&#125;<br/><br/>@@ -334,7 +360,9 @@ void *handlep;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ni.tail = ni.tail->next;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;ncp->nc_configs = ni.tail;<br/><br/>- return(ni.tail->ncp);<br/><br/>+ result = ni.tail->ncp;<br/><br/>+ mutex_unlock(&ni_lock);<br/><br/>+ return(result);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/> &#125;<br/><br/> <br/><br/>@@ -368,8 +396,10 @@ void *handlep;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; nc_handlep->valid = NC_INVALID;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; nc_handlep->flag = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; nc_handlep->nc_configs = NULL;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if (–ni.ref > 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;free(nc_handlep);<br/><br/>+ mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp;return(0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/> <br/><br/>@@ -381,6 +411,7 @@ void *handlep;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ni.eof = ni.ref = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ni.head = NULL;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; ni.tail = NULL;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; while (q) &#123;<br/><br/>&nbsp;&nbsp;p = q->next;<br/><br/>&nbsp;&nbsp;if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups); @@ -390,9 +421,10 @@ void *handlep;<br/><br/>&nbsp;&nbsp;q = p;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; free(nc_handlep);<br/><br/>-<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; fclose(nc_file);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; nc_file = NULL;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&nc_file_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; return (0);<br/><br/> &#125;<br/><br/> <br/><br/>@@ -440,16 +472,20 @@ getnetconfigent(netid)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* If all the netconfig db has been read and placed into the list and<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* there is no match for the netid, return NULL.<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_lock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if (ni.head != NULL) &#123;<br/><br/>&nbsp;&nbsp;for (list = ni.head; list; list = list->next) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strcmp(list->ncp->nc_netid, netid) == 0) &#123;<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(dup_ncp(list->ncp));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&#125;<br/><br/>- if (ni.eof == 1) /* that’s all the entries */<br/><br/>+ if (ni.eof == 1) &#123;/* that’s all the entries */<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mutex_unlock(&ni_lock);<br/><br/>&nbsp;&nbsp; return(NULL);<br/><br/>+ &#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>-<br/><br/>+&nbsp;&nbsp;&nbsp;&nbsp;mutex_unlock(&ni_lock);<br/><br/> <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if ((file = fopen(NETCONFIG, “r”)) == NULL) &#123;<br/><br/>&nbsp;&nbsp;nc_error = NC_NONETCONFIG;<br/>
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 前些年在sina 企业mail的rpc在freebsd老是倒，在网上看到一个哥们说烂]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>