PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/mysqlDB/mysql-test/lib/mtr_timer.pl

https://github.com/olliolli/me.store
Perl | 145 lines | 90 code | 28 blank | 27 comment | 5 complexity | 4fab2bc240b0a6a89b99a715b295f9dc MD5 | raw file
  1. # -*- cperl -*-
  2. # This is a library file used by the Perl version of mysql-test-run,
  3. # and is part of the translation of the Bourne shell script with the
  4. # same name.
  5. use Carp qw(cluck);
  6. use Socket;
  7. use Errno;
  8. use strict;
  9. #use POSIX ":sys_wait_h";
  10. use POSIX 'WNOHANG';
  11. sub mtr_init_timers ();
  12. sub mtr_timer_start($$$);
  13. sub mtr_timer_stop($$);
  14. sub mtr_timer_stop_all($);
  15. sub mtr_timer_waitpid($$$);
  16. ##############################################################################
  17. #
  18. # Initiate a structure shared by all timers
  19. #
  20. ##############################################################################
  21. sub mtr_init_timers () {
  22. my $timers = { timers => {}, pids => {}};
  23. return $timers;
  24. }
  25. ##############################################################################
  26. #
  27. # Start, stop and poll a timer
  28. #
  29. # As alarm() isn't portable to Windows, we use separate processes to
  30. # implement timers. That is why there is a mtr_timer_waitpid(), as this
  31. # is where we catch a timeout.
  32. #
  33. ##############################################################################
  34. sub mtr_timer_start($$$) {
  35. my ($timers,$name,$duration)= @_;
  36. if ( exists $timers->{'timers'}->{$name} )
  37. {
  38. # We have an old running timer, kill it
  39. mtr_timer_stop($timers,$name);
  40. }
  41. FORK:
  42. {
  43. my $tpid= fork();
  44. if ( ! defined $tpid )
  45. {
  46. if ( $! == $!{EAGAIN} ) # See "perldoc Errno"
  47. {
  48. mtr_debug("Got EAGAIN from fork(), sleep 1 second and redo");
  49. sleep(1);
  50. redo FORK;
  51. }
  52. else
  53. {
  54. mtr_error("can't fork");
  55. }
  56. }
  57. if ( $tpid )
  58. {
  59. # Parent, record the information
  60. $timers->{'timers'}->{$name}->{'pid'}= $tpid;
  61. $timers->{'timers'}->{$name}->{'duration'}= $duration;
  62. $timers->{'pids'}->{$tpid}= $name;
  63. }
  64. else
  65. {
  66. # Child, redirect output and exec
  67. # FIXME do we need to redirect streams?
  68. # Don't do the ^C cleanup in the timeout child processes!
  69. # There is actually a race here, if we get ^C after fork(), but before
  70. # clearing the signal handler.
  71. $SIG{INT}= 'DEFAULT';
  72. $0= "mtr_timer(timers,$name,$duration)";
  73. sleep($duration);
  74. exit(0);
  75. }
  76. }
  77. }
  78. sub mtr_timer_stop ($$) {
  79. my ($timers,$name)= @_;
  80. if ( exists $timers->{'timers'}->{$name} )
  81. {
  82. my $tpid= $timers->{'timers'}->{$name}->{'pid'};
  83. # FIXME as Cygwin reuses pids fast, maybe check that is
  84. # the expected process somehow?!
  85. kill(9, $tpid);
  86. # As the timers are so simple programs, we trust them to terminate,
  87. # and use blocking wait for it. We wait just to avoid a zombie.
  88. waitpid($tpid,0);
  89. delete $timers->{'timers'}->{$name}; # Remove the timer information
  90. delete $timers->{'pids'}->{$tpid}; # and PID reference
  91. return 1;
  92. }
  93. else
  94. {
  95. mtr_debug("Asked to stop timer \"$name\" not started");
  96. return 0;
  97. }
  98. }
  99. sub mtr_timer_stop_all ($) {
  100. my $timers= shift;
  101. foreach my $name ( keys %{$timers->{'timers'}} )
  102. {
  103. mtr_timer_stop($timers, $name);
  104. }
  105. return 1;
  106. }
  107. sub mtr_timer_timeout ($$) {
  108. my ($timers,$pid)= @_;
  109. return "" unless exists $timers->{'pids'}->{$pid};
  110. # We got a timeout
  111. my $name= $timers->{'pids'}->{$pid};
  112. mtr_timer_stop($timers, $timers->{'timers'}->{$name});
  113. return $name;
  114. }
  115. 1;