--- deliantra/server/lib/cf.pm 2006/12/31 17:17:23 1.105 +++ deliantra/server/lib/cf.pm 2006/12/31 17:29:22 1.106 @@ -176,15 +176,26 @@ JSON::Syck::Dump $_[0] } -# main coro must never ever "block" except in Event -# sync_job ensures this by running the job in a coroutine -# and waiting in Event while the server is otherwise frozen +=item cf::sync_job { BLOCK } + +The design of crossfire+ requires that the main coro ($Coro::main) is +always able to handle events or runnable, as crossfire+ is only partly +reentrant. Thus "blocking" it by e.g. waiting for I/O is not acceptable. + +If it must be done, put the blocking parts into C. This will run +the given BLOCK in another coroutine while waiting for the result. The +server will be frozen during this time, so the block should either finish +fast or be very important. + +=cut + sub sync_job(&) { my ($job) = @_; my $busy = 1; my @res; + # TODO: use suspend/resume instead local $FREEZE = 1; my $coro = Coro::async { @@ -1273,12 +1284,19 @@ # initialisation sub _perl_reload() { + # can/must only be called in main + if ($Coro::current != $Coro::main) { + warn "can only reload from main coroutine\n"; + return; + } + warn "reloading..."; - eval { - local $FREEZE = 1; + local $FREEZE = 1; + cf::emergency_save; - cf::emergency_save; + eval { + # if anything goes wrong in here, we should simply crash as we already saved # cancel all watchers for (Event::all_watchers) { @@ -1347,9 +1365,14 @@ warn "reattach"; _global_reattach; }; - warn $@ if $@; - warn "reloaded"; + if ($@) { + warn $@; + warn "error while reloading, exiting."; + exit 1; + } + + warn "reloaded successfully"; }; sub perl_reload() {