客户质询的现象是:

Slony-I运行中,log中发现FATAL信息:

FATAL  storeListen: unknown node ID 

出现了上述错误后,再看后继的log,又恢复正常运行了。

客户的问题在于:如何看待这个错误信息,它是否是设计上就是这样的?

言外之意,这到底是否是一个bug?

设计上是否是这样,是无从知晓的,只有问Vendor。而我的想法是,先分析源代码看看:

/* ----------
* SlonWatchdog
* ----------
*/
static void
SlonWatchdog(void)
{

slon_log(SLON_INFO, "slon: watchdog process started\n");
slon_log(SLON_CONFIG, "slon: watchdog ready - pid = %d\n", slon_watchdog_pid);
slon_worker_pid = fork();
if (slon_worker_pid == )
{
SlonMain();
exit(-);
}

if (install_signal_handler(SIGUSR1,sighandler) == SIG_ERR)
{
slon_log(SLON_FATAL, "slon: SIGUSR1 signal handler setup failed -(%d) %s\n", errno, strerror(errno));
slon_exit(-);
}

slon_log(SLON_CONFIG, "slon: worker process created - pid = %d\n",
slon_worker_pid);
while(!shutdown)
{
while ((pid = wait(&child_status)) != slon_worker_pid)
{

}

slon_log(SLON_CONFIG, "slon: child terminated %s: %d; pid: %d, current worker pid: %d\n",
termination_reason,return_code, pid, slon_worker_pid);
switch (watchdog_status)
{

case SLON_WATCHDOG_NORMAL:
case SLON_WATCHDOG_RETRY:
watchdog_status = SLON_WATCHDOG_RETRY;
if (child_status != )
{
slon_log(SLON_CONFIG, "slon: restart of worker in 10 seconds\n");
(void)sleep();
}
else
{
slon_log(SLON_CONFIG, "slon: restart of worker\n");
}
if (watchdog_status == SLON_WATCHDOG_RETRY)
{
slon_worker_pid=fork();
if(slon_worker_pid == )
{
worker_restarted=;
SlonMain();
exit(-);
}

watchdog_status=SLON_WATCHDOG_NORMAL;
continue;
}
break;
default:
shutdown=;
break;
} /*switch*/
}/*while*/

}
/* ----------
* SlonMain
* ----------
*/
static void
SlonMain(void)
{

for (i = , n = PQntuples(res); i < n; i++)
{

rtcfg_storePath(pa_server, pa_conninfo, pa_connretry);
}
PQclear(res);

}
/* ----------
* rtcfg_storePath
* ----------
*/
void
rtcfg_storePath(int pa_server, char *pa_conninfo, int pa_connretry)
{

/*
* Store the (new) conninfo to the node
*/
slon_log(SLON_CONFIG, "storePath: pa_server=%d pa_client=%d pa_conninfo=\"%s\" pa_connretry=%d\n",
pa_server, rtcfg_nodeid, pa_conninfo, pa_connretry);

/*
* Eventually start communicating with that node
*/
rtcfg_startStopNodeThread(node);
}
/* ----------
* rtcfg_startStopNodeThread
* ----------
*/
static void
rtcfg_startStopNodeThread(SlonNode * node)
{

if (sched_get_status() == SCHED_STATUS_OK && node->no_active)
{
/*
* Make sure the node worker exists
*/
switch (node->worker_status)
{
case SLON_TSTAT_NONE:
if (pthread_create(&(node->worker_thread), NULL, remoteWorkerThread_main, (void *)node) < )
{

}
node->worker_status = SLON_TSTAT_RUNNING;
break;

}
}

}
/* ----------
* slon_remoteWorkerThread
*
* Listen for events on the local database connection. This means, events
* generated by the local node only.
* ----------
*/
void *
remoteWorkerThread_main(void *cdata)
{

while (true)
{

else /* not SYNC */
{

else if (strcmp(event->ev_type, "STORE_LISTEN") == )
{

if (li_receiver == rtcfg_nodeid)
rtcfg_storeListen(li_origin, li_provider);

}

}

}

}
/* ----------
* rtcfg_storeListen
* ----------
*/
void
rtcfg_storeListen(int li_origin, int li_provider)
{

node = rtcfg_findNode(li_provider);
if (!node)
{
slon_log(SLON_FATAL,"storeListen: unknown node ID %d\n", li_provider);
slon_retry();
return;
}

}
#define slon_retry() \
do { \
pthread_mutex_lock(&slon_watchdog_lock); \
if (slon_watchdog_pid >= ) { \
slon_log(SLON_DEBUG2, "slon_retry() from pid=%d\n", slon_pid); \
(void) kill(slon_watchdog_pid, SIGUSR1); \
slon_watchdog_pid = -; \
} \
pthread_mutex_unlock(&slon_watchdog_lock); \
pthread_exit(NULL); \
} while () /* ----------
* sighandler
* ----------
*/
static void
sighandler(int signo)
{
switch (signo)
{

case SIGUSR1:
watchdog_status = SLON_WATCHDOG_RETRY;
slon_terminate_worker();
break;

}
}
/* ----------
* slon_terminate_worker
* ----------
*/
void
slon_terminate_worker()
{
(void) kill(slon_worker_pid, SIGKILL);
}

上述是对代码的简略整理。

在其中:

  SlonWatchdog函数中,通过fork生成子进程。

 此子进程的SlonMain函数里、通过rtcfg_storePath --> rtcfg_storePath -->rtcfg_startStopNodeThread的调用关系,

 作了一个线程,该线程启动是,调用 remoteWorkerThread_main 函数。

remoteWorkerThread_main函数里,调用rtcfg_storeListen函数的时候,

如果获得 Node情报的时候,发生了错误,就会导致向SlonWatchdog运行时的主进程发送SIGUSR信号。

另一方面:

 主进程的SlonWatchdog函数中,早已经准备了对应SIGUSR信号的函数sighandler。

 在此sighandler函数中,SIGUSR信号发生时,会把上述的子进程kill掉。

 而且,此主进程中通过wait调用,准备好了当上述子进程一旦被kill掉或者自己死掉时的代码逻辑:

通过while循环,再次采用fork操作,调用fork后子进程的SlonMain函数,一切又周而复始了:

     如果SlonMain函数调用rtcfg_storeListen失败,就再次发生死亡,回到主进程再次fork;

如果成功,就跳出循环,进入下一步的处理。

Slony-I中对storelisten出错的处理的更多相关文章

  1. Ubuntu虚机中SVN连接出错,虚机本机可正常CO,CIN,解决方法

    Ubuntu虚机中SVN连接出错,虚机本机可正常CO,CIN,外面机器无法正常连接. 解决: 虚机换个IP即可正常连接,原因不明,有可能为公司网管对该IP做了某些限制. PS:VMware中只需将网络 ...

  2. 向Oracle数据库中插入数据出错:ORA-01036 无效的变量名或数据

    向Oracle数据库中插入数据出错: 经过排查,因为Update数据时没有出错,所以OracleHelper没有问题: 看异常信息提示:无效的变量和数据,应该是SQL语句的问题,调试时所传的实例Use ...

  3. VS的ASP.NET项目中cshtml关键词出错 红线,当前上下文中不存在名称

    [参考]VS的ASP.NET项目中cshtml突然出错,当前上下文中不存在名称“ViewBag” 原因:web.config 配置错误 这种情况是因为两个web.config文件版本不匹配,需要进行修 ...

  4. NFine中权限判断出错的问题

    NFine中权限判断出错的问题 问题描述:登录后点击栏目一,弹出了窗口一,再点击栏目二,弹出了窗口二,然后再点击窗口一,再执行窗口一中的操作时,发现已没有任何权限,调试后发现在HandlerAutho ...

  5. 【动手学深度学习】Jupyter notebook中 import mxnet出错

    问题描述 打开d2l-zh目录,使用jupyter notebook打开文件运行,import mxnet 出现无法导入mxnet模块的问题, 但是命令行运行是可以导入mxnet模块的. 原因: 激活 ...

  6. (转)WCF中调用WebService出错,大家帮忙看看,回答就有分

    http://bbs.csdn.net/topics/390542345 在WCF项目里面添加了一个WebService引用,然后在我们调用这个WCF服务时,老出错,提示在 ServiceModel  ...

  7. delphi中 dataset容易出错的地方

    最近写delphi项目,用到的数据集中的dataset,一直修改exception啊,写下过程. 在对数据集进行任何操作之前,首先要打开数据集.要打开数据集,可以把Active属性设为True,例如: ...

  8. 解决Pycharm中matplotlib画图出错问题(AttributeError: module 'matplotlib' has no attribute 'verbose')

    最近在Linux中使用pycharm过程中使用matplotlib无法画图,总是提示错误 /usr/bin/python3. /home/leo/PycharmProjects/untitled1/E ...

  9. 发现Mathematica中求逆出错

    发现Mathematica中应用Inverse求逆时出错.

随机推荐

  1. hdu 5469 Antonidas (dfs+剪枝)2015 ACM/ICPC Asia Regional Shanghai Online

    题意: 给出一棵树,再给出每个节点上的值(一个char字符)这些值以一个字符串s1表示,然后给出一个s2字符串,问在这棵树上是否存在两个点,从一个点走到另一个点所经过的路径上的char字符组成的字符串 ...

  2. .net发邮件 附件文件名乱码

    .net发邮件 附件文件名乱码,可以下载以下补丁安装. https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.asp ...

  3. js中DOM集合的动态特性

    先引出一个问题:通过调用getElements*()这样的方法返回来类(伪)数组,能对其本身的元素进行排序吗? 答案是不能,因为这些对象的都是NodeList . NamedNodeMap 或 HTM ...

  4. 黑马程序员——Block数据类型

    Block数据类型,又被称为代码段.因为它可以封装一段代码.苹果官方建议多用block.因为在多线程控制.异步任务,集合遍历.集合排序.动画转场等方面用的很多. Block的特点: 1.Block 用 ...

  5. 为什么要Cssreset

    1.CssReset是什么?由于html标签在各浏览器的默认样式解析出来的有所不同.例如<ul>标签在IE.firefox.chrome浏览器下默认边距是不一样的.各浏览器的默认样,会给我 ...

  6. Android 设置 横屏 竖屏 (转)

    http://2960629.blog.51cto.com/2950629/701227 方法一:在AndroidManifest.xml中配置 如果不想让软件在横竖屏之间切换,最简单的办法就是在项目 ...

  7. RFID之UID

    1 Unique identifier (UID) The VICCs are uniquely identified by a 64 bits unique identifier (UID). Th ...

  8. PHPCMS V9实现硬件地址MAC绑定访问技术实现

    目的:会员登录需要 用户名.密码.身份识别码(新增字段) 效果:  解决方法: 目前数据库中macaddress字段已经添加,修改了phpcms\modules\member\index.php 63 ...

  9. WS之cxf与spring整合1

    1.在web.xml中加入CXFServlet: <!-- 下面表示所有来自/cxfservice/*的请求,都交给 CXFServlet来处理 .--> <servlet>  ...

  10. C#获取ftp文件最后修改时间

    public static DateTime GetFileModifyDateTime(string ftpServerIP,string ftpFolder,string ftpUserID,st ...