客户质询的现象是:

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. js 只能输入数字和小数点

    <html><head><meta http-equiv="content-Type" content="text/html;charset ...

  2. JSTL获取list的大小,jstl获取list 的长度,EL表达式获取list的长度,EL表达式获取list大小

    在jsp页面中不能通过${list.size}取列表长度,而是 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" pref ...

  3. Android 自定义dialogfragment

    在用dialogfragment的时候我们可能会不喜欢系统自带的黑色边框,那怎么办呢? dialofragment提供可供修改样式的方法setStyle(style,R.style.MyTryUseD ...

  4. leetcode:Longest Palindromic Substring(求最大的回文字符串)

    Question:Given a string S, find the longest palindromic substring in S. You may assume that the maxi ...

  5. 现代浏览器内置的可等效替代jQuery的功能

    jQuery的体积在不断的增大.新功能要不断增加,这是必然结果.虽然从版本1.8.3开始的瘦身效果明显,但不可否认的是,对于移动手机端的网 页开发,它仍然是不可接受的.当然,jQuery不是铁板一块, ...

  6. [Lua]入门教程

    什么是Lua Lua 是一个小巧的脚本语言.是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Rober ...

  7. Linux下的GitHub安装与简单配置教程

    1.GitHub简介 Git是一个分布式版本控制系统,与其相对的是CVS.SVN等集中式的版本控制系统. 2.Git的安装 1)安装Git a.查看与使用 在ubuntu下可以使用如下命令进行查看系统 ...

  8. Git 常用操作。

    1.本地文件被修改后,却想要撤销所有的修改. SVN中可以简单地将被修改的文件直接删除,重新Update一下. Git中本以为可以将文件直接删除然后pull一下,然而却是不行的. 可以使用Revert ...

  9. 非对称认证方式 可以用在 asp.net webapi 的安全机制里面

    //Client端调用 static void Main(string[] args) { string publicKey = "DpLMCOihcYI2i6DaMbso9Dzo1miy7 ...

  10. rhel5.5 Oracle10g安装记录

    ---恢复内容开始--- Rhel5.5 Oracle10g安装成功截图如下