# This is a patch for Event-0.58 to update it to Event-0.59 # # To apply this patch: # STEP 1: Chdir to the source directory. # STEP 2: Run the 'applypatch' program with this patch file as input. # # If you do not have 'applypatch', it is part of the 'makepatch' package # that you can fetch from the Comprehensive Perl Archive Network: # http://www.perl.com/CPAN/authors/Johan_Vromans/makepatch-x.y.tar.gz # In the above URL, 'x' should be 2 or higher. # # To apply this patch without the use of 'applypatch': # STEP 1: Chdir to the source directory. # If you have a decent Bourne-type shell: # STEP 2: Run the shell with this file as input. # If you don't have such a shell, you may need to manually create # the files as shown below. # STEP 3: Run the 'patch' program with this file as input. # # These are the commands needed to create/delete files/directories: # touch 'demo/variable_repeater.t' chmod 0444 'demo/variable_repeater.t' touch 't/leak2.t' chmod 0444 't/leak2.t' # # This command terminates the shell and need not be executed manually. exit # #### End of Preamble #### #### Patch data follows #### gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/ChangeLog' '/usr/tmp/mp4882.d/new/Event-0.59/ChangeLog' Index: ./ChangeLog --- ./ChangeLog Mon Nov 22 17:04:29 1999 +++ ./ChangeLog Thu Jan 20 10:30:41 2000 @@ -1,3 +1,19 @@ +2000-01-20 Joshua Pritikin <[EMAIL PROTECTED]> + + * Release 0.59. + + * Fixed serious memory leak (isolated by + [EMAIL PROTECTED]). Added t/leak2.t. + +2000-01-19 Joshua Pritikin <[EMAIL PROTECTED]> + + * Doc for timeout_cb (demanded by [EMAIL PROTECTED] :-). + +1999-12-15 Joshua Pritikin <[EMAIL PROTECTED]> + + * Added demo/variable_timer.t along with minor doc + update. ([EMAIL PROTECTED]) + 1999-11-22 Joshua Pritikin <[EMAIL PROTECTED]> * Release 0.58. gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/Event.xs' '/usr/tmp/mp4882.d/new/Event-0.59/Event.xs' Index: ./Event.xs --- ./Event.xs Mon Nov 22 16:35:49 1999 +++ ./Event.xs Wed Jan 19 11:45:47 2000 @@ -94,10 +94,12 @@ static void dbg_count_memory(int id, int MemoryCount[id] += cnt; } -#if DEBUGGING +#if EVENT_MEMORY_DEBUG # define EvNew(id, ptr, size, type) dbg_count_memory(id,1); New(0,ptr,size,type) +# define EvFree(id, ptr) STMT_START { dbg_count_memory(id,-1); safefree(ptr); } +STMT_END #else # define EvNew(x, ptr, size, type) New(0,ptr,size,type) +# define EvFree(id, ptr) safefree(ptr) #endif static int ActiveWatchers=0; /* includes WaACTIVE + queued events */ @@ -309,7 +311,7 @@ void _memory_counters() PPCODE: { -#ifdef DEBUGGING +#ifdef EVENT_MEMORY_DEBUG int xx; for (xx=0; xx < MAX_MEMORYCOUNT; xx++) XPUSHs(sv_2mortal(newSViv(MemoryCount[xx]))); gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/MANIFEST' '/usr/tmp/mp4882.d/new/Event-0.59/MANIFEST' Index: ./MANIFEST --- ./MANIFEST Mon Nov 22 17:12:49 1999 +++ ./MANIFEST Thu Jan 20 09:32:27 2000 @@ -26,6 +26,7 @@ demo/inactivity.t demo/process.pm demo/readline.t demo/spin_io.t +demo/variable_repeater.t lib/Event.pm lib/Event.pod lib/Event/EventAPI.h @@ -51,6 +52,7 @@ t/idle.t t/idle2.t t/io.t t/leak.t +t/leak2.t t/loop.t t/now.t t/reenter.t gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/TODO' '/usr/tmp/mp4882.d/new/Event-0.59/TODO' Index: ./TODO --- ./TODO Mon Nov 22 17:07:03 1999 +++ ./TODO Thu Jan 20 10:05:56 2000 @@ -14,6 +14,14 @@ optimization queue events from both sides? try to hoist system calls from the inner loop [EMAIL PROTECTED] signal discussion: + The API rsignal overrides the current signal handler. If the signal + watcher is cancelled (or otherwise disabled) then rsignal is reset to + SIG_DFL. You bring up a good point here. Maybe the original handler + should be restored. On the other hand, assignment to %SIG will mess + up Event watchers so maybe Event should refuse to watch a signal if a + handler is already installed. + loop StarvePrio? gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/hook.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/hook.c' Index: ./c/hook.c --- ./c/hook.c Mon Nov 22 13:41:05 1999 +++ ./c/hook.c Wed Jan 19 10:40:07 2000 @@ -44,7 +44,7 @@ static void pe_cancel_hook(pe_qcallback if (qcb->is_perl) SvREFCNT_dec((SV*)qcb->callback); PE_RING_DETACH(&qcb->ring); - safefree(qcb); + EvFree(2, qcb); } static void pe_map_check(pe_ring *List) gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/idle.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/idle.c' Index: ./c/idle.c --- ./c/idle.c Mon Nov 22 13:41:05 1999 +++ ./c/idle.c Wed Jan 19 10:46:57 2000 @@ -21,6 +21,7 @@ static void pe_idle_dtor(pe_watcher *ev) SvREFCNT_dec(ip->max_interval); SvREFCNT_dec(ip->min_interval); pe_watcher_dtor(ev); + EvFree(3, ev); } static void pe_idle_start(pe_watcher *ev, int repeating) { gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/io.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/io.c' Index: ./c/io.c --- ./c/io.c Mon Nov 22 16:51:30 1999 +++ ./c/io.c Wed Jan 19 10:47:21 2000 @@ -29,6 +29,7 @@ static void pe_io_dtor(pe_watcher *_ev) PE_RING_DETACH(&ev->ioring); SvREFCNT_dec(ev->handle); pe_watcher_dtor(_ev); + EvFree(4, _ev); } static void pe_io_start(pe_watcher *_ev, int repeat) { gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/queue.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/queue.c' Index: ./c/queue.c --- ./c/queue.c Mon Nov 22 15:50:39 1999 +++ ./c/queue.c Wed Jan 19 16:54:06 2000 @@ -149,6 +149,9 @@ static void pe_queue_pending() { } static int one_event(double tm) { /**INVOKE**/ + /*if (SvIVX(DebugLevel) >= 4) + warn("Event: ActiveWatchers=%d\n", ActiveWatchers);*/ + pe_signal_asynccheck(); if (!PE_RING_EMPTY(&AsyncCheck)) pe_map_check(&AsyncCheck); gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/signal.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/signal.c' Index: ./c/signal.c --- ./c/signal.c Mon Nov 22 13:41:06 1999 +++ ./c/signal.c Wed Jan 19 10:48:05 2000 @@ -41,6 +41,11 @@ static pe_watcher *pe_signal_allocate(HV return (pe_watcher*) ev; } +static void pe_signal_dtor(pe_watcher *ev) { + pe_watcher_dtor(ev); + EvFree(5, ev); +} + static void pe_signal_start(pe_watcher *_ev, int repeat) { pe_signal *ev = (pe_signal*) _ev; int sig = ev->signal; @@ -138,6 +143,7 @@ static void boot_signal() { ++sigp; } memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); + vt->dtor = pe_signal_dtor; vt->start = pe_signal_start; vt->stop = pe_signal_stop; pe_register_vtbl(vt, gv_stashpv("Event::signal",1), &event_vtbl); gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/tied.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/tied.c' Index: ./c/tied.c --- ./c/tied.c Mon Nov 22 13:41:06 1999 +++ ./c/tied.c Wed Jan 19 10:46:25 2000 @@ -10,6 +10,11 @@ static pe_watcher *pe_tied_allocate(HV * return (pe_watcher*) ev; } +static void pe_tied_dtor(pe_watcher *ev) { + pe_watcher_dtor(ev); + EvFree(6, ev); +} + static void pe_tied_start(pe_watcher *ev, int repeat) { HV *stash = SvSTASH(SvRV(ev->mysv)); GV *gv; @@ -92,6 +97,7 @@ static void boot_tied() { pe_watcher_vtbl *vt = &pe_tied_vtbl; memcpy(vt, &pe_watcher_base_vtbl, sizeof(pe_watcher_base_vtbl)); vt->did_require = 1; /* otherwise tries to autoload Event::Event! */ + vt->dtor = pe_tied_dtor; vt->start = pe_tied_start; vt->stop = pe_tied_stop; vt->alarm = pe_tied_alarm; gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/timer.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/timer.c' Index: ./c/timer.c --- ./c/timer.c Mon Nov 22 13:44:02 1999 +++ ./c/timer.c Wed Jan 19 10:48:25 2000 @@ -16,6 +16,7 @@ static void pe_timer_dtor(pe_watcher *ev pe_timer *tm = (pe_timer*) ev; SvREFCNT_dec(tm->interval); pe_watcher_dtor(ev); + EvFree(7, ev); } static void pe_timer_start(pe_watcher *ev, int repeat) { gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/typemap.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/typemap.c' Index: ./c/typemap.c --- ./c/typemap.c Mon Nov 22 13:41:07 1999 +++ ./c/typemap.c Wed Jan 19 11:01:14 2000 @@ -22,7 +22,7 @@ static SV *wrap_watcher(void *ptr, HV *s while ((mg = *mgp)) mgp = &mg->mg_moremagic; - EvNew(8, mg, 1, MAGIC); + New(0, mg, 1, MAGIC); Zero(mg, 1, MAGIC); mg->mg_type = '~'; mg->mg_obj = (SV*) ptr; /* NOT refcnt'd */ gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/unix_io.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/unix_io.c' Index: ./c/unix_io.c --- ./c/unix_io.c Mon Nov 22 13:41:07 1999 +++ ./c/unix_io.c Wed Jan 19 10:40:29 2000 @@ -75,7 +75,7 @@ static void pe_sys_multiplex(double time int ret; if (pollMax < IOWatchCount) { if (Pollfd) - safefree(Pollfd); + EvFree(9, Pollfd); pollMax = IOWatchCount+5; EvNew(9, Pollfd, pollMax, struct pollfd); IOWatch_OK = 0; gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/var.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/var.c' Index: ./c/var.c --- ./c/var.c Mon Nov 22 13:41:07 1999 +++ ./c/var.c Wed Jan 19 11:01:30 2000 @@ -16,6 +16,7 @@ static void pe_var_dtor(pe_watcher *ev) pe_var *wv = (pe_var *)ev; SvREFCNT_dec(wv->variable); pe_watcher_dtor(ev); + EvFree(10, ev); } static void pe_tracevar(pe_watcher *wa, SV *sv, int got) { @@ -81,7 +82,7 @@ static void pe_var_start(pe_watcher *_ev mg->mg_virtual = &PL_vtbl_uvar; *mgp = mg; - EvNew(12, ufp, 1, struct ufuncs); + EvNew(8, ufp, 1, struct ufuncs); ufp->uf_val = ev->events & PE_R? tracevar_r : 0; ufp->uf_set = ev->events & PE_W? tracevar_w : 0; ufp->uf_index = (IV) ev; @@ -119,8 +120,8 @@ static void pe_var_stop(pe_watcher *_ev) *mgp = mg->mg_moremagic; - safefree(mg->mg_ptr); - safefree(mg); + EvFree(8, mg->mg_ptr); + EvFree(11, mg); } static void _var_restart(pe_watcher *ev) { gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/c/watcher.c' '/usr/tmp/mp4882.d/new/Event-0.59/c/watcher.c' Index: ./c/watcher.c --- ./c/watcher.c Mon Nov 22 15:32:56 1999 +++ ./c/watcher.c Wed Jan 19 16:51:41 2000 @@ -49,8 +49,8 @@ static void pe_watcher_cancel_events(pe_ pe_event *ev; while (!PE_RING_EMPTY(&wa->events)) { pe_ring *lk = wa->events.prev; - PE_RING_DETACH(lk); ev = (pe_event*) lk->self; + dequeEvent(ev); pe_event_release(ev); } } @@ -74,7 +74,7 @@ static void pe_watcher_dtor(pe_watcher * SvREFCNT_dec(wa->desc); if (wa->stats) Estat.dtor(wa->stats); - safefree(wa); + /* safefree(wa); do it yourself */ } /********************************** *******************************/ @@ -243,7 +243,7 @@ static void boot_pe_watcher() { vt = &pe_watcher_base_vtbl; vt->stash = 0; vt->did_require = 0; - vt->dtor = pe_watcher_dtor; + vt->dtor = 0; vt->start = pe_watcher_nostart; vt->stop = pe_watcher_nostop; vt->alarm = pe_watcher_alarm; gdiff -up /dev/null '/usr/tmp/mp4882.d/new/Event-0.59/demo/variable_repeater.t' Index: ./demo/variable_repeater.t --- ./demo/variable_repeater.t Wed Dec 31 19:00:00 1969 +++ ./demo/variable_repeater.t Wed Dec 22 17:00:07 1999 @@ -0,0 +1,14 @@ +#!./perl -w +# contributed by [EMAIL PROTECTED] + +use Event qw(loop); + +$w = Event->timer(interval => 1); +$w->cb(sub { + my $next = rand(10); + print(scalar localtime(Event::time()), ": waiting ", + $next, " sec\n"); + $w->interval($next); + }); + +loop(); gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/lib/Event.pm' '/usr/tmp/mp4882.d/new/Event-0.59/lib/Event.pm' Index: ./lib/Event.pm --- ./lib/Event.pm Mon Nov 22 17:04:52 1999 +++ ./lib/Event.pm Thu Jan 20 10:29:07 2000 @@ -13,7 +13,7 @@ use Carp; eval { require Carp::Heavy; }; # work around perl_call_pv bug XXX use vars qw($VERSION @EXPORT_OK $API $DebugLevel $Eval $DIED $Now); -$VERSION = '0.58'; +$VERSION = '0.59'; # If we inherit DynaLoader then we inherit AutoLoader; Bletch! require DynaLoader; gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/lib/Event.pod' '/usr/tmp/mp4882.d/new/Event-0.59/lib/Event.pod' Index: ./lib/Event.pod --- ./lib/Event.pod Mon Nov 22 17:09:36 1999 +++ ./lib/Event.pod Wed Jan 19 10:24:02 2000 @@ -168,9 +168,9 @@ Reports whether the C<$watcher> is suspe Extra attributes: min => $seconds, max => $seconds -The callback is invoked only when no events are pending. In the -callback is not triggered by idling, an event will be generated at -least every C<max> seconds and not more often than C<min> seconds. +The callback is invoked only when no events are pending. If there is +never a chance to idle, an event will be generated at least every +C<max> seconds and not more often than C<min> seconds. =item inactivity @@ -204,7 +204,7 @@ calculated relative to the current time =item io Extra attributes: fd => $fd, poll => 'rwe', got => 'rwet', -[timeout => $seconds, hard => $bool] +[timeout => $seconds, hard => $bool, timeout_cb => \&code] The callback is invoked when the file descriptor, C<fd>, has data to be read, written, or pending exceptions. C<fd> can be a GLOB, an @@ -213,6 +213,9 @@ IO::Handle object, or a file number (fil Note that it is your option whether to have multiple watchers per file handle or to use a single watcher for all event conditions. +If timeout_cb is set then timeouts use this alternate callback instead +of the main callback. + =item signal Extra attribute: signal => $str @@ -298,7 +301,8 @@ Signals in quick succession can be clump =item interval => $seconds -How long between repeating timeouts. +How long between repeating timeouts. The C<at> attribute is +recalculated using C<interval> upon callback return. =item level => $priority @@ -398,6 +402,14 @@ actually want to stop a watcher then use =item timeout => $seconds The number of seconds before a watcher times out. + +=item timeout_cb => \&code + +=item timeout_cb => [$class_or_object, $method_name] + +This is an optional attribute for use when it is desired that timeouts +be serviced in a separate code path than normal events. When this +attribute is unset, timeouts are serviced by C<cb>. =item var => $ref gdiff -up '/usr/tmp/mp4882.d/old/Event-0.58/lib/Event/EventAPI.h' '/usr/tmp/mp4882.d/new/Event-0.59/lib/Event/EventAPI.h' Index: ./lib/Event/EventAPI.h --- ./lib/Event/EventAPI.h Mon Nov 22 16:18:48 1999 +++ ./lib/Event/EventAPI.h Wed Jan 19 16:47:42 2000 @@ -25,8 +25,8 @@ struct pe_watcher { IV running; /* SAVEINT */ U32 flags; SV *desc; - pe_ring all; - pe_ring events; /* queued events */ + pe_ring all; /* all watchers */ + pe_ring events; /* this watcher's queued events */ HV *FALLBACK; I16 event_counter; /* refcnt? XXX */ I16 prio; gdiff -up /dev/null '/usr/tmp/mp4882.d/new/Event-0.59/t/leak2.t' Index: ./t/leak2.t --- ./t/leak2.t Wed Dec 31 19:00:00 1969 +++ ./t/leak2.t Thu Jan 20 10:14:59 2000 @@ -0,0 +1,47 @@ +#!./perl -w +# +# Test script to check the memory consumption +# of an Event loop which installs, handles and +# cancels a number of IO watchers (recursively). +# +# For extra diagnostics, Event.pm can be built with +# -DEVENT_MEMORY_DEBUG. +# +# If the script succeeds, the final memory check +# replies something like this: +# "1-29509-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0" +# (all slots except of the first two ones should +# be 0 - the second number may differ). +# +# J. Stenzel ([EMAIL PROTECTED]) +# + +use Test; plan test => 2; + +use Event; +# $Event::DebugLevel = 3; + +sub check {warn "[DBG] ", join('-', Event::_memory_counters), "\n";} + +sub iosub { + for (my $l=0; $l<=5; $l++) { + Event->io( + fh => \*STDIO, timeout => "0.5$l", + repeat => 1, cb => \&iosub, + prio => 5); + } + $_[0]->w->cancel; +} + +Event->io(fh => \*STDIO, timeout => 0.5, repeat => 1, + cb => \&iosub, prio => 5); + +Event->timer(prio => 1, after => 3, + cb => sub { + $_->cancel foreach Event::all_watchers; + ok !defined Event::all_watchers; + } + ); + +Event::loop(); +ok 1; #### End of Patch data #### #### ApplyPatch data follows #### # Data version : 1.0 # Date generated : Thu Jan 20 10:43:54 2000 # Generated by : makepatch 2.00 (2.0BETA) # Recurse directories : Yes # p 'ChangeLog' 19702 948382241 0100444 # p 'Event.xs' 17098 948300347 0100444 # p 'MANIFEST' 775 948378747 0100444 # p 'TODO' 750 948380756 0100444 # p 'c/hook.c' 1614 948296407 0100444 # p 'c/idle.c' 3488 948296817 0100444 # p 'c/io.c' 5078 948296841 0100444 # p 'c/queue.c' 5118 948318846 0100444 # p 'c/signal.c' 3665 948296885 0100444 # p 'c/tied.c' 2593 948296785 0100444 # p 'c/timer.c' 2111 948296905 0100444 # p 'c/typemap.c' 3653 948297674 0100444 # p 'c/unix_io.c' 6438 948296429 0100444 # p 'c/var.c' 4082 948297690 0100444 # p 'c/watcher.c' 8585 948318701 0100444 # c 'demo/variable_repeater.t' 0 945900007 0100444 # p 'lib/Event.pm' 4159 948382147 0100444 # p 'lib/Event.pod' 18595 948295442 0100444 # p 'lib/Event/EventAPI.h' 5346 948318462 0100444 # c 't/leak2.t' 0 948381299 0100444 #### End of ApplyPatch data #### #### End of Patch kit [created: Thu Jan 20 10:43:54 2000] #### #### Checksum: 513 17072 2998 #### -- "Does `competition' have an abstract purpose?" via, but not speaking for Deutsche Bank
