首先简要介绍一下程序打算做什么:它将从文本文件中读取一个URL列表,一次一个.对于每个URL,它将调用子例程(将URL作为参数传递),并向其发送HTTP HEAD请求.一旦接收到HTTP响应头,它将从响应中打印“服务器头”字段.
对于每个URL,它启动一个调用上述子例程的新线程.
问题:主要问题是程序有时会间歇性崩溃.其他时候运行正常.它似乎是不可靠的代码,我相信有一种方法使其可靠地工作.
代码:
#!/usr/bin/perl use strict; use warnings; use threads; use WWW::Mechanize; no warnings 'uninitialized'; open(INPUT,'<','urls.txt') || die("Couldn't open the file in read mode\n"); print "Starting main program\n"; my @threads; while(my $url = <INPUT>) { chomp $url; my $t = threads->new(\&sub1,$url); push(@threads,$t); } foreach (@threads) { $_->join; } print "End of main program\n"; sub sub1 { my $site = shift; sleep 1; my $mech = WWW::Mechanize->new(); $mech->agent_alias('Windows IE 6'); # trap any error which occurs while sending an HTTP HEAD request to the site eval{$mech->head($site);}; if($@) { print "Error connecting to: ".$site."\n"; } my $response = $mech->response(); print $site." => ".$response->header('Server'),"\n"; }
问题:
如何使这个程序可靠地工作,零星崩溃的原因是什么?
根据下面链接的文档,它将等待线程执行完成.我正确地调用join方法吗?
http://perldoc.perl.org/threads.html
在C中,调用CreateThread()之后调用Sleep()开始执行线程.
关于崩溃:当上述Perl代码意外和偶尔崩溃时,我收到错误消息:“Perl命令行解释器已停止工作”
崩溃的细节:
Fault Module Name: ntdll.dll Exception Code: c0000008
上述异常代码对应于:STATUS_INVALID_HANDLE
也许这对应于线程的无效句柄.
我的Perl安装细节:
Summary of my perl5 (revision 5 version 14 subversion 2) configuration: Platform: osname=MSWin32,osvers=5.2,archname=MSWin32-x86-multi-thread useithreads=define
操作系统的详细信息:Win 7 Ultimate,64位操作系统.
希望这个信息足以找到问题的根本原因并纠正代码.
解决方法
Perl的线程通过在同一操作系统进程中创建多个解释器实例来实现.这将每个线程中的Perl代码与所有其他线程隔离(这是没有共享的).它不(或不能)做的是隔离不在perl控制下的代码.也就是说,具有以C编写的组件的任何模块.例如,快速查看WWW :: Mechanize表明,如果安装了zlib,则可以使用zlib进行压缩.如果这被使用,并且C代码不够线程安全,这可能是一个可能崩溃的问题.因此,如果您想确保您的Perl应用程序在线程下工作良好,则必须遍历所使用的所有模块(以及所有使用的模块),并检查它们是否具有非Perl部件,或者这些部件是线程安全的.对于大多数非常重要的程序,这是一个不合理的工作量(或者对您可以使用的CPAN模块有不合理的限制).
这可能是线程在Perl中不被使用的原因的很大一部分.