我有一个正在执行段错误的脚本,我对解决它的方式不太满意,所以我想在这里发布这个问题,以了解更多关于它的原因,也许是一个更好的解决方案。
这是我的脚本的作用(删除了一些详细代码以保留它的“核心”):
# Here's a query I need to do every X seconds to monitor progress of other tasks
# This is apparently the key to my segfault problem
my $stmt = $dbh->prepare($query);
my $all_done = 0;
while(!$all_done) {
$self->debug("Waiting for $n blocker tasks to be finished");
# Execute query to pull the status of the tasks from DB
$stmt->execute();
my $pending = [];
while(my $hr = $stmt->fetchrow_hashref()) {
push @{$pending}, $hr->{'TASK_NAME'} if ($hr->{'STATUS'} ne 'COMPLETE');
}
if(scalar(@{$pending}) > 0) {
$all_done = 0;
sleep($sleep_gap);
}
else { $all_done = 1; }
}
现在,脚本运行良好,大部分时间。但是,当脚本的 3 个或更多实例并行运行时(相同的脚本,单独的进程,而不是线程),它会出现段错误。
我是怎么解决的?我通过在 while(!$all_done) 循环期间每次调用 DBH::prepare 来解决它。
因此,即使多个进程并行运行,此代码也不会出现段错误。我重复了几次错误,始终如一,然后我对新代码做了同样的事情。我很肯定在循环内移动语句可以解决问题。
任何想法为什么会发生这种情况?
我正在使用 perl 5.8 和 perl-DBI 1.609 版。
这也是脚本段错误时 strace 的输出:
read(5, "\1\7\0\0\6\0\0\0\0\0\20\27\234\312\272\221eG2;\33S\364\230\313\220\221Bxp\4\7"..., 2064) = 263
write(4, "\1\31\0\0\6\0\0\0\0\0\21i \1\1\0\0\0\2\0\0\0\3^!)\4\4\0\0\0\0"..., 281) = 281
read(4, "\0\177\0\0\6\0\0\0\0\0\v\5\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0 \10\6"..., 2064) = 127
write(2, "debug:Waiting for 1 blocker task"..., 49debug:Waiting for 1 blocker tasks to be finished
) = 49
write(5, "\0\252\0\0\6\0\0\0\0\0\3^\20p\200\0\0\2\0\0\0\0\0\0\0\0\1\r\0\0\0\0"..., 170) = 170
read(5, "\0\301\0\0\6\0\0\0\0\0\6\"\2\0\0\0@\0\0\0\0\0\0\0\0\0\0\0\7 ru"..., 2064) = 193
write(5, "\1]\0\0\6\0\0\0\0\0\3^\21)\200\0\0\0\0\0\0\1\234\0\0\0\1\r\0\0\0\0"..., 349) = 349
read(5, "\0y\0\0\6\0\0\0\0\0\10\6\0S\254b\f\0\t\0\0\1\0\0\0\1\0\0\0\0\0\0"..., 2064) = 121
write(5, "\0000\0\0\6\0\0\0\0\0\3h\22\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 48) = 48
read(5, "\0\26\0\0\6\0\0\0\0\0\10\2\0\0\0\t\5\0\0\0\21\0", 2064) = 22
time(NULL) = 1333827285
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({10, 0}, {10, 0}) = 0
time(NULL) = 1333827295
write(4, "\1\31\0\0\6\0\0\0\0\0\21i\"\1\1\0\0\0\3\0\0\0\3^#)\4\4\0\0\0\0"..., 281) = 281
read(4, "\0\177\0\0\6\0\0\0\0\0\v\5\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0 \10\6"..., 2064) = 127
write(2, "debug:Waiting for 1 blocker task"..., 49debug:Waiting for 1 blocker tasks to be finished
) = 49
write(5, "\0)\0\0\6\0\0\0\0\0\21i\23\1\1\0\0\0\1\0\0\0\3N\24\2\0\0\0@\0\0"..., 41) = 41
read(5, "\1>\0\0\6\0\0\0\0\0\20\27\234\312\272\221eG2;\33S\364\230\313\220\221Bxp\4\7"..., 2064) = 318
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
[ Process PID=22767 runs in 32 bit mode. ]