… | |
… | |
371 | sub write_runtime { |
371 | sub write_runtime { |
372 | my $guard = cf::lock_acquire "write_runtime"; |
372 | my $guard = cf::lock_acquire "write_runtime"; |
373 | |
373 | |
374 | my $runtime = "$LOCALDIR/runtime"; |
374 | my $runtime = "$LOCALDIR/runtime"; |
375 | |
375 | |
|
|
376 | warn "starting to write runtime...\n";#d# |
376 | my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644 |
377 | my $fh = aio_open "$runtime~", O_WRONLY | O_CREAT, 0644 |
377 | or return; |
378 | or return; |
378 | |
379 | |
379 | my $value = $cf::RUNTIME + 90 + 10; |
380 | my $value = $cf::RUNTIME + 90 + 10; |
380 | # 10 is the runtime save interval, for a monotonic clock |
381 | # 10 is the runtime save interval, for a monotonic clock |
… | |
… | |
390 | close $fh |
391 | close $fh |
391 | or return; |
392 | or return; |
392 | |
393 | |
393 | aio_rename "$runtime~", $runtime |
394 | aio_rename "$runtime~", $runtime |
394 | and return; |
395 | and return; |
|
|
396 | |
|
|
397 | warn "... done writing runtime.\n";#d# |
395 | |
398 | |
396 | 1 |
399 | 1 |
397 | } |
400 | } |
398 | |
401 | |
399 | =item cf::datalog type => key => value, ... |
402 | =item cf::datalog type => key => value, ... |
… | |
… | |
2435 | |
2438 | |
2436 | die $$res unless "ARRAY" eq ref $res; |
2439 | die $$res unless "ARRAY" eq ref $res; |
2437 | |
2440 | |
2438 | return wantarray ? @$res : $res->[-1]; |
2441 | return wantarray ? @$res : $res->[-1]; |
2439 | } else { |
2442 | } else { |
|
|
2443 | reset_signals; |
2440 | local $SIG{__WARN__}; |
2444 | local $SIG{__WARN__}; |
|
|
2445 | local $SIG{__DIE__}; |
2441 | eval { |
2446 | eval { |
2442 | local $SIG{__DIE__}; |
|
|
2443 | close $fh1; |
2447 | close $fh1; |
2444 | |
2448 | |
2445 | my @res = eval { $cb->(@args) }; |
2449 | my @res = eval { $cb->(@args) }; |
2446 | syswrite $fh2, Coro::Storable::freeze +($@ ? \"$@" : \@res); |
2450 | syswrite $fh2, Coro::Storable::freeze +($@ ? \"$@" : \@res); |
2447 | }; |
2451 | }; |
… | |
… | |
2923 | prio => 6, |
2927 | prio => 6, |
2924 | cb => \&IO::AIO::poll_cb, |
2928 | cb => \&IO::AIO::poll_cb, |
2925 | ); |
2929 | ); |
2926 | } |
2930 | } |
2927 | |
2931 | |
|
|
2932 | my $_log_backtrace; |
|
|
2933 | |
2928 | sub _log_backtrace { |
2934 | sub _log_backtrace { |
2929 | my ($msg, @addr) = @_; |
2935 | my ($msg, @addr) = @_; |
2930 | |
2936 | |
|
|
2937 | $msg =~ s/\n//; |
|
|
2938 | |
|
|
2939 | # limit the # of concurrent backtraces |
|
|
2940 | if ($_log_backtrace < 2) { |
|
|
2941 | ++$_log_backtrace; |
2931 | async { |
2942 | async { |
2932 | my @bt = fork_call { |
2943 | my @bt = fork_call { |
2933 | @addr = map { sprintf "%x", $_ } @addr; |
2944 | @addr = map { sprintf "%x", $_ } @addr; |
|
|
2945 | my $self = (-f "/proc/$$/exe") ? "/proc/$$/exe" : $^X; |
2934 | open my $fh, "exec addr2line -C -f -i -e \Q$^X\E @addr 2>&1 |" |
2946 | open my $fh, "exec addr2line -C -f -i -e \Q$self\E @addr 2>&1 |" |
2935 | or die "addr2line: $!"; |
2947 | or die "addr2line: $!"; |
2936 | |
2948 | |
2937 | my @funcs; |
2949 | my @funcs; |
2938 | my @res = <$fh>; |
2950 | my @res = <$fh>; |
2939 | chomp for @res; |
2951 | chomp for @res; |
2940 | while (@res) { |
2952 | while (@res) { |
2941 | my ($func, $line) = splice @res, 0, 2, (); |
2953 | my ($func, $line) = splice @res, 0, 2, (); |
2942 | push @funcs, "[$func] $line"; |
2954 | push @funcs, "[$func] $line"; |
|
|
2955 | } |
|
|
2956 | |
|
|
2957 | @funcs |
2943 | } |
2958 | }; |
2944 | |
2959 | |
2945 | @funcs |
2960 | LOG llevInfo, "[ABT] $msg\n"; |
|
|
2961 | LOG llevInfo, "[ABT] $_\n" for @bt; |
|
|
2962 | --$_log_backtrace; |
2946 | }; |
2963 | }; |
2947 | |
2964 | } else { |
2948 | $msg =~ s/\n//; |
|
|
2949 | |
|
|
2950 | LOG llevInfo, "[ABT] $msg\n"; |
2965 | LOG llevInfo, "[ABT] $msg\n"; |
2951 | LOG llevInfo, "[ABT] $_\n" for @bt; |
2966 | LOG llevInfo, "[ABT] [suppressed]\n"; |
2952 | }; |
2967 | } |
2953 | } |
2968 | } |
2954 | |
2969 | |
2955 | # load additional modules |
2970 | # load additional modules |
2956 | use cf::pod; |
2971 | use cf::pod; |
2957 | |
2972 | |