--- deliantra/server/lib/cf.pm 2007/01/02 11:08:36 1.120 +++ deliantra/server/lib/cf.pm 2007/01/04 00:53:54 1.131 @@ -10,7 +10,7 @@ use Safe; use Safe::Hole; -use Coro 3.3; +use Coro 3.3 (); use Coro::Event; use Coro::Timer; use Coro::Signal; @@ -73,8 +73,7 @@ # a special map that is always available our $LINK_MAP; - -our $EMERGENCY_POSITION = $cf::CFG{emergency_position} || ["/world/world_105_115", 5, 37]; +our $EMERGENCY_POSITION; ############################################################################# @@ -247,6 +246,22 @@ } } +=item cf::async { BLOCK } + +Like C, but runs the given BLOCK in an eval and only logs the +error instead of exiting the server in case of a problem. + +=cut + +sub async(&) { + my ($cb) = @_; + + Coro::async { + eval { $cb->() }; + warn $@ if $@; + } +} + =item cf::sync_job { BLOCK } The design of crossfire+ requires that the main coro ($Coro::main) is @@ -303,12 +318,7 @@ sub coro(&) { my $cb = shift; - my $coro; $coro = async { - eval { - $cb->(); - }; - warn $@ if $@; - }; + my $coro = &cf::async ($cb); $coro->on_destroy (sub { delete $EXT_CORO{$coro+0}; @@ -1155,7 +1165,8 @@ sub change_all_map_light { my ($change) = @_; - $_->change_map_light ($change) for values %cf::MAP; + $_->change_map_light ($change) + for grep $_->outdoor, values %cf::MAP; } sub try_load_header($) { @@ -1176,6 +1187,7 @@ $map } +sub find_map; sub find_map { my ($path, $origin) = @_; @@ -1212,7 +1224,6 @@ # per-player maps become, after loading, normal maps $map->per_player (0) if $path->{user_rel}; } - #Coro::Timer::sleep 1;#d# $map->path ($key); $map->{path} = $path; @@ -1221,7 +1232,9 @@ if ($map->should_reset) { $map->reset; - $map = find_map $path; + undef $guard; + $map = find_map $path + or return; } $cf::MAP{$key} = $map @@ -1310,11 +1323,13 @@ sub swap_out { my ($self) = @_; + # save first because save cedes + $self->save; + return if $self->players; return if $self->in_memory != cf::MAP_IN_MEMORY; return if $self->{deny_save}; - $self->save; $self->clear; $self->in_memory (cf::MAP_SWAPPED); } @@ -1537,7 +1552,7 @@ # should happen only on crashes if ($pl->ob->{_link_pos}) { $pl->ob->enter_link; - Coro::async { + cf::async { # we need this sleep as the login has a concurrent enter_exit running # and this sleep increases chances of the player not ending up in scorn Coro::Timer::sleep 1; @@ -1556,7 +1571,7 @@ $self->enter_link; - (Coro::async { + (cf::async { $path = new cf::path $path; my $map = cf::map::find_map $path->as_string; @@ -1628,9 +1643,8 @@ $self->enter_link; - (Coro::async { + (cf::async { unless (eval { - prepare_random_map $exit if $exit->slaying eq "/!"; @@ -1702,7 +1716,8 @@ # this weird shuffling is so that direct followup queries # get handled first - my $queue = delete $ns->{query_queue}; + my $queue = delete $ns->{query_queue} + or return; # be conservative, not sure how that can happen, but we saw a crash here (shift @$queue)->[1]->($msg); @@ -1729,12 +1744,7 @@ sub cf::client::coro { my ($self, $cb) = @_; - my $coro; $coro = async { - eval { - $cb->(); - }; - warn $@ if $@; - }; + my $coro = &cf::async ($cb); $coro->on_destroy (sub { delete $self->{_coro}{$coro+0}; @@ -1916,14 +1926,12 @@ my $path = cf::localdir . "/database.pst"; sub db_load() { - warn "loading database $path\n";#d# remove later $DB = stat $path ? Storable::retrieve $path : { }; } my $pid; sub db_save() { - warn "saving database $path\n";#d# remove later waitpid $pid, 0 if $pid; if (0 == ($pid = fork)) { $DB->{_meta}{version} = 1; @@ -1981,6 +1989,16 @@ local $/; *CFG = YAML::Syck::Load <$fh>; + + $EMERGENCY_POSITION = $CFG{emergency_position} || ["/world/world_105_115", 5, 37]; + + if (exists $CFG{mlockall}) { + eval { + $CFG{mlockall} ? &mlockall : &munlockall + and die "WARNING: m(un)lockall failed: $!\n"; + }; + warn $@ if $@; + } } sub main { @@ -2193,5 +2211,7 @@ }, ); +END { cf::emergency_save } + 1