免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3711 | 回复: 6
打印 上一主题 下一主题

perl的多线程怀疑内存泄漏,大家帮忙看看这个小程序是不是有问题? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-07-06 11:46 |只看该作者 |倒序浏览
本帖最后由 aweizai 于 2011-07-06 13:34 编辑

有一段perl代码用到了perl 的fork 生成多个子线程,客户执行后说是有很多子线程的执行被忽略掉了,我看了客户提供的执行日志,发现最后一个子线程在主线程关闭后反而能正常执行,怀疑子线程占用的资源是不是都要等到主线程结束后才释放,在本地测试了一下,重现不了这个问题,也没发现有内存泄漏。
大家忙我看看吧,如果有应该要怎么改?
  1. #!/usr/local/bin/perl -w

  2. use strict;

  3. use POSIX ":sys_wait_h";
  4. use threads::shared;
  5. use JSON;
  6. use Data::Dumper;
  7. use Getopt::Long qw(GetOptions);

  8. my @feeds = ();
  9. my $children_num;
  10. my $help;
  11. my $debug;
  12. my $verbose;


  13. my $main_start = time();

  14. print "\nStart process_feeds_multi.pl, main process pid is $$\n" if $debug;

  15. my @children;
  16. my $curr_children_num :shared = 0;
  17. my $feeds_index :shared = 0;
  18. my $front_pid;

  19. $children_num = 1 unless $children_num;
  20. @feeds = split ',', join ',', @feeds;
  21. my $feeds_to_run;

  22. pipe(RD,WT) or die "Can't open pipe: $!\n";

  23. my $f_pid = fork();
  24. if ( $f_pid ) {
  25.     $front_pid = $f_pid;
  26.     close WT;
  27.     $feeds_to_run = jsonToObj(<RD>);
  28. }
  29. elsif ( $f_pid == 0) {
  30.     if ( $debug ) {
  31.         my $ppid = getppid();
  32.         print "Create child process to get active feeds, its pid is $$ and parent pid is $ppid \n";
  33.     }

  34.      $feeds_to_run = &get_active_feeds(@feeds);

  35.      if ( $verbose ) {
  36.          my $feeds_str = join (', ', map { $_->{feed_id} } @$feeds_to_run);
  37.          print "Active feeds: [ $feeds_str ] \n";
  38.      }

  39.     my $feeds_json = objToJson($feeds_to_run);
  40.     close RD;
  41.     select WT;
  42.     $| = 1;
  43.     print $feeds_json;
  44.     exit 0;
  45. }
  46. else {
  47.     die "couldn't fork:$!";
  48. }
  49. if ( waitpid( $front_pid, 0 ) ) {
  50.     print "Finish getting active feeds, done with child-process $front_pid \n" if $debug;

  51.     while ( $curr_children_num < ($children_num - 1) && $feeds_index < scalar (@$feeds_to_run) ) {
  52.         &create_child();
  53.     }

  54.     while ( $feeds_index < scalar (@$feeds_to_run) ) {
  55.         &create_child();
  56.         my $child = undef;
  57.         do {
  58.             $child = waitpid(-1, WNOHANG);
  59.         } until $child > 0;
  60.     }
  61. }

  62. print "Done with parent-process $$, all child-processes are created.\n" if $debug;

  63. exit;

  64. sub create_child() {
  65.     my $pid = fork();
  66.     if ( $pid ) {
  67.         $curr_children_num++;
  68.         $feeds_index++;
  69.         push ( @children, $pid );
  70.     }
  71.     elsif ( $pid == 0 ) {
  72.         my $child_begin_time = time();
  73.         if ( $debug ) {
  74.             my $ppid = getppid();
  75.             print "Create a new child-process, its pid is $$ and parent-process is $ppid \n";
  76.         }

  77.         my $feed_id = $tmp_data->{feed_id};
  78.         print "Start producing feed $feed_id ...\n" if $debug;

  79.         process_feed( $tmp_data );

  80.         my $child_end_time = time();
  81.         if ( $verbose ) {
  82.             my $cost_time = $child_end_time - $child_begin_time;
  83.             print "Done with producing " if $debug;
  84.             print "feed $feed_id, cost $cost_time s\n";
  85.         }

  86.         print "Done with child-process $$ and exit.\n" if $debug;
  87.         exit 0;
  88.     }
  89.     else {
  90.         die "couldn't fork:$!";
  91.     }
  92.     return 1;
  93. }

  94. sub get_active_feeds {
  95.     my @limit = @_;
  96.         ...
  97.     return \@feeds;
  98. }

  99. sub process_feed {
  100.     ...
  101. }

复制代码
运行日志大概如此
  1. Start process_feeds_multi.pl, main process pid is 5706
  2. Create child process to get active feeds, its pid is 5708 and parent pid is 5706
  3. Get active feeds:
  4. Active feeds: [ 34, 44, 62, 63, 65, 66, 67, 72, 78, 79, 84, 85, 86, 87, 88, 91, 92, 97, 100, 104, 106, 110, 115, 116, 119, 122, 132, 134, 135, 137, 138, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 154, 156, 157, 158, 159, 160, 161, 162, 163, 171, 172, 175, 176, 184, 185, 187, 188, 189, 190, 196, 200, 209, 210, 211, 214, 215, 227, 231, 232, 233, 234, 235, 236, 237, 238, 241, 247, 248, 249, 250, 253, 257, 258, 260, 267, 269, 271, 272, 274, 275, 278, 279, 280, 282, 283, 284, 285, 286, 287, 288, 292, 293, 294, 295, 300, 301, 302, 305, 306, 307, 309, 310, 311, 315, 318, 319, 322, 323, 324, 325, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 342, 343, 344, 345, 346, 347, 348, 349, 350, 356, 357, 358, 359, 360, 361, 362, 365, 368, 372, 375, 376, 377, 384, 386, 387, 388, 389, 390, 392, 394, 397, 398, 400, 402, 403, 404, 405, 406, 407, 409, 410, 412, 418, 419, 420, 421, 424, 427, 429, 431, 433, 434, 435, 436, 437, 438, 439, 445, 447, 448, 449, 450, 452, 453, 454, 456 ]
  5. Finsh getting active feeds, done with child-process 5708
  6. Create a new child-process, its pid is 5710 and parent-process is 5706
  7. Start producing feed 44 ...
  8. Done with producing feed 44, cost 27 s
  9. Done with child-process 5710 and exit.
  10. Create a new child-process, its pid is 5973 and parent-process is 5706
  11. Start producing feed 62 ...
  12. Done with producing feed 62, cost 1083 s
  13. Done with child-process 5973 and exit.
  14. Create a new child-process, its pid is 5709 and parent-process is 5706
  15. Start producing feed 34 ...
  16. Done with producing feed 34, cost 1111 s
  17. Done with child-process 5709 and exit.
  18. Create a new child-process, its pid is 8084 and parent-process is 5706
  19. Start producing feed 65 ...
  20. Done with producing feed 65, cost 789 s
  21. Done with child-process 8084 and exit.
  22. Create a new child-process, its pid is 9448 and parent-process is 5706
  23. Start producing feed 66 ...
  24. Done with producing feed 66, cost 73 s
  25. Done with child-process 9448 and exit.
  26. Create a new child-process, its pid is 9491 and parent-process is 5706
  27. Start producing feed 67 ...
  28. .....
  29. .....
  30. Create a new child-process, its pid is 21087 and parent-process is 5706
  31. Start producing feed 196 ...
  32. Create a new child-process, its pid is 21088 and parent-process is 5706
  33. Start producing feed 200 ...
  34. Create a new child-process, its pid is 21089 and parent-process is 5706
  35. Start producing feed 209 ...
  36. Create a new child-process, its pid is 21090 and parent-process is 5706
  37. Start producing feed 210 ...
  38. Create a new child-process, its pid is 21091 and parent-process is 5706
  39. Start producing feed 211 ...
  40. .....
  41. .....
  42. Create a new child-process, its pid is 21287 and parent-process is 5706
  43. Start producing feed 454 ...
  44. Done with parent-process 5706, all child-processes are created.
  45. Create a new child-process, its pid is 21288 and parent-process is 5706
  46. Start producing feed 456 ...
  47. Create a new child-process, its pid is 20787 and parent-process is 5706
  48. Start producing feed 184 ...
  49. Done with producing feed 184, cost 723 s
  50. Done with child-process 20787 and exit.
复制代码

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
2 [报告]
发表于 2011-07-06 13:08 |只看该作者
fork 怎么成多线程了,没用 threads 用 :shared 有用吗

论坛徽章:
0
3 [报告]
发表于 2011-07-06 13:33 |只看该作者
回复 2# zhlong8


    有引用的,代码里面贴少这个引用了。
use threads::shared;

论坛徽章:
0
4 [报告]
发表于 2011-07-06 13:38 |只看该作者
应该说是进程更合适,或者ithread, waitpid好像是可以释放进程资源的,代码中已经用了waitpid了还会造成内存泄漏吗?

论坛徽章:
0
5 [报告]
发表于 2011-07-06 16:43 |只看该作者
多进程怎么使用线程的共享方法呢

论坛徽章:
0
6 [报告]
发表于 2011-07-06 16:44 |只看该作者
多进程怎么使用线程的共享方法呢

论坛徽章:
0
7 [报告]
发表于 2011-07-06 17:21 |只看该作者
回复 6# nsnake


    是的,通过测试,我也发现变量共享实际上没起作用。当初设置这个变量共享的目的是控制进程数。现在其实不共享的变量程序也能达到控制进程数的目的(后面是每结束一个进程再新建一个进程,所以我就还没去掉这个共享的),等之后做修改的时候我会把这些不合理的地方都修改一下。

现在主要的问题是内存泄漏,据我所知,只要用了waitpid或者wait,进程结束后,resource就会自动回收,这个程序里面是用了waitpid的,但是还是有内存泄漏,不知道怎么回事。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP