客户质询的现象是:

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. C# "error CS1729: 'XXClass' does not contain a constructor that takes 0 arguments"的解决方案

    出现这种错误的原因时,没有在子类的构造函数中指出仅有带参构造函数的父类的构造参数. 具体来讲就是: 当子类要重用父类的构造函数时, C# 语法通常会在子类构造函数后面调用 : base( para_t ...

  2. Linux常用文件管理命令

    Command Description cat filename 查看文件内容. cd dirname 改变所在目录. cp file1 file2 复制文件或目录. file filename 查看 ...

  3. django-grappelli 安装配置

    在python34/scripts文件夹下pip3 install django-grappelli pip安装一般会装在python34的tools或lib之类的文件夹下,一定要找到那个文件夹,gr ...

  4. html中的div、td 、p 等容器内强制换行和不换行的实现

    div.td .p 等容器内强制换行和不换行,在某些情况下还是比较实用的,下面本文整理了一些相关方面的知识,并有具体的实现方法,需要的朋友可以参考下1.强制不换行,同时以省略号结尾. 代码如下:< ...

  5. ansible定时任务模块和用户组模块使用

    接上篇,还是一些基础模块的使用,这里主要介绍的是系统模块的使用. 下面例子都进行过相关的实践,从而可以直接进行使用相关的命令. 3.用户模块的使用 用户模块主要用来管理用户账号和用户的属性(对远程主机 ...

  6. Epic - Coin Change

    Something cost $10.25 and the customer pays with a $20 bill, the program will print out the most eff ...

  7. 开扒php内核函数,第三篇 implode

    一开始觉得implode挺容易实现,但是写着写着才发现是挺复杂的,不说啦 来看看implode的用法吧 <?php $arr = array('Hello','World!','Beautifu ...

  8. 排列组合+组合数取模 HDU 5894

    // 排列组合+组合数取模 HDU 5894 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 // 思路: // 定好m个人 相邻人之间k个座位 剩下就剩n-( ...

  9. phpcms V9实现QQ登陆OAuth2.0

    phpcmsV9使用的QQ登陆依然是OAuth1.0,但现在腾讯已经不审核使用OAuth1.0的网站了.这对于使用pc的站长来讲是一个无比巨大的坑.经过对phpcms论坛的一位同学做的插件进行修改,现 ...

  10. ShellExecute的各种用法

    一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOperation, lpFile, lpParameters, lpDire ...