Slony-I中对storelisten出错的处理
客户质询的现象是:
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出错的处理的更多相关文章
- Ubuntu虚机中SVN连接出错,虚机本机可正常CO,CIN,解决方法
Ubuntu虚机中SVN连接出错,虚机本机可正常CO,CIN,外面机器无法正常连接. 解决: 虚机换个IP即可正常连接,原因不明,有可能为公司网管对该IP做了某些限制. PS:VMware中只需将网络 ...
- 向Oracle数据库中插入数据出错:ORA-01036 无效的变量名或数据
向Oracle数据库中插入数据出错: 经过排查,因为Update数据时没有出错,所以OracleHelper没有问题: 看异常信息提示:无效的变量和数据,应该是SQL语句的问题,调试时所传的实例Use ...
- VS的ASP.NET项目中cshtml关键词出错 红线,当前上下文中不存在名称
[参考]VS的ASP.NET项目中cshtml突然出错,当前上下文中不存在名称“ViewBag” 原因:web.config 配置错误 这种情况是因为两个web.config文件版本不匹配,需要进行修 ...
- NFine中权限判断出错的问题
NFine中权限判断出错的问题 问题描述:登录后点击栏目一,弹出了窗口一,再点击栏目二,弹出了窗口二,然后再点击窗口一,再执行窗口一中的操作时,发现已没有任何权限,调试后发现在HandlerAutho ...
- 【动手学深度学习】Jupyter notebook中 import mxnet出错
问题描述 打开d2l-zh目录,使用jupyter notebook打开文件运行,import mxnet 出现无法导入mxnet模块的问题, 但是命令行运行是可以导入mxnet模块的. 原因: 激活 ...
- (转)WCF中调用WebService出错,大家帮忙看看,回答就有分
http://bbs.csdn.net/topics/390542345 在WCF项目里面添加了一个WebService引用,然后在我们调用这个WCF服务时,老出错,提示在 ServiceModel ...
- delphi中 dataset容易出错的地方
最近写delphi项目,用到的数据集中的dataset,一直修改exception啊,写下过程. 在对数据集进行任何操作之前,首先要打开数据集.要打开数据集,可以把Active属性设为True,例如: ...
- 解决Pycharm中matplotlib画图出错问题(AttributeError: module 'matplotlib' has no attribute 'verbose')
最近在Linux中使用pycharm过程中使用matplotlib无法画图,总是提示错误 /usr/bin/python3. /home/leo/PycharmProjects/untitled1/E ...
- 发现Mathematica中求逆出错
发现Mathematica中应用Inverse求逆时出错.
随机推荐
- C# "error CS1729: 'XXClass' does not contain a constructor that takes 0 arguments"的解决方案
出现这种错误的原因时,没有在子类的构造函数中指出仅有带参构造函数的父类的构造参数. 具体来讲就是: 当子类要重用父类的构造函数时, C# 语法通常会在子类构造函数后面调用 : base( para_t ...
- Linux常用文件管理命令
Command Description cat filename 查看文件内容. cd dirname 改变所在目录. cp file1 file2 复制文件或目录. file filename 查看 ...
- django-grappelli 安装配置
在python34/scripts文件夹下pip3 install django-grappelli pip安装一般会装在python34的tools或lib之类的文件夹下,一定要找到那个文件夹,gr ...
- html中的div、td 、p 等容器内强制换行和不换行的实现
div.td .p 等容器内强制换行和不换行,在某些情况下还是比较实用的,下面本文整理了一些相关方面的知识,并有具体的实现方法,需要的朋友可以参考下1.强制不换行,同时以省略号结尾. 代码如下:< ...
- ansible定时任务模块和用户组模块使用
接上篇,还是一些基础模块的使用,这里主要介绍的是系统模块的使用. 下面例子都进行过相关的实践,从而可以直接进行使用相关的命令. 3.用户模块的使用 用户模块主要用来管理用户账号和用户的属性(对远程主机 ...
- Epic - Coin Change
Something cost $10.25 and the customer pays with a $20 bill, the program will print out the most eff ...
- 开扒php内核函数,第三篇 implode
一开始觉得implode挺容易实现,但是写着写着才发现是挺复杂的,不说啦 来看看implode的用法吧 <?php $arr = array('Hello','World!','Beautifu ...
- 排列组合+组合数取模 HDU 5894
// 排列组合+组合数取模 HDU 5894 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 // 思路: // 定好m个人 相邻人之间k个座位 剩下就剩n-( ...
- phpcms V9实现QQ登陆OAuth2.0
phpcmsV9使用的QQ登陆依然是OAuth1.0,但现在腾讯已经不审核使用OAuth1.0的网站了.这对于使用pc的站长来讲是一个无比巨大的坑.经过对phpcms论坛的一位同学做的插件进行修改,现 ...
- ShellExecute的各种用法
一.利用系统默认的邮件收发器发送电子邮件 Uses ..., ShellAPI; Var lpHwnd: HWND; lpOperation, lpFile, lpParameters, lpDire ...