Too many different dynamic events crash server
----------------------------------------------

                 Key: CORE-3859
                 URL: http://tracker.firebirdsql.org/browse/CORE-3859
             Project: Firebird Core
          Issue Type: Bug
          Components: Engine
    Affects Versions: 2.0.7, 2.1.4, 2.0.6, 2.1.3, 2.1.5
         Environment: CentOS 5 (5.5 and 5.8)
            Reporter: Pete Cervasio


A recent change to how our software is using triggers to create dynamic events 
has been found to crash the firebird server.

Our software is watching for changes to a 'PLAYLIST' table which has entries 
containing station number and date and time values.  Since the system doesn't 
care about changes that are not within the immediate time frame a dynamic set 
of events was created in the form of 'PLAYLIST_INSERTED_x_yyyy-mm-dd_hh' where 
'x' is a station number, 'yyyy-mm-dd' is the contents of a date field, and 'hh' 
is the first two characters of the scheduled time field.  At the start of each 
hour, the program registers interest in the current and next hours.

After approximately 616 event registrations and event occurrences, the Firebird 
server will crash.  Changing the length of the event names to use a single 
character 'I' instead of 'PLAYLIST_INSERTED_' makes that number jump a bit 
higher, but the crash still happens.

Operating system : CentOS 5.8 (but also tested on 5.5)
Firebird server : Tested on versions 2.0.6, 2.0.7, 2.1.4 and 2.1.5 release 
candidate (from 22 May 2012)

Server log when the crash happens:

~>tail /opt/firebird/firebird.log 

serv1-0000.sbcglobal.net (Client)       Mon May 28 14:26:04 2012
        /opt/firebird/bin/fbguard: /opt/firebird/bin/fbserver terminated 
abnormally (-1)



serv1-0000.sbcglobal.net (Client)       Mon May 28 14:26:04 2012
        /opt/firebird/bin/fbguard: guardian starting bin/fbserver


Sample database:

-- ------------------------------------------------------------
-- ISQL scriptlet:

create database '/tmp/event_fail.fdb';

-- A table with the bare minimum to show this problem:
create table playlist (
    station_number     integer not null,
    scheduled_date     date not null,
    scheduled_time     varchar(12) not null
);

-- Two triggers to go with it:
set term ;!!

create trigger pe_playlist_deleted for playlist 
       active after delete position 0 as
begin
    post_event 'PLAYLIST_DELETED_' || old.station_number || '_' ||
    old.scheduled_date || '_' || substring(old.scheduled_time from 1 for 2);
end !!

create trigger pe_playlist_inserted for playlist 
       active after insert position 0 as
begin
    post_event 'PLAYLIST_INSERTED_' || new.station_number || '_' ||
    new.scheduled_date || '_' || substring(new.scheduled_time from 1 for 2);
end !!
-- Two stored procedure with same params as our regular ones
create procedure insert_log_entry (
    station_num integer,
    dt date,
    tm varchar(12),
    id varchar(250),
    cluster integer,
    mandatory varchar(1))
returns
    (curr integer)
as
begin
    insert into playlist values (:station_num, :dt, :tm);
    curr = 0;
end !!

-- Unused in perl script, my pascal calls on it, though
create procedure remove_log_entry (
    station_num integer,
    curr integer)
returns
    (next integer)
as
begin
    delete from playlist where station_number = :station_num;
    next = 0;
end !!

set term ;!!

commit;

You might want to add that to your aliases:

echo "event_fail = /tmp/event_fail.fdb" >> /opt/firebird/aliases.conf

And here is a perl script which will show the error.  I'm sure real perl 
programmers will cringe at this.

#!/usr/bin/perl -w
#
# Note: This needs DBI::InterBase.  It might work with DBI::Firebird
# but I haven't tried it.
#
# Usage: $0 dbserver:database

use strict;
use DBI;
use POSIX qw(strftime mktime);

my $dsn = shift;         # $ARGV[0] - Specified as dbhost:dbname.

my $DB_USER = 'sysdba';
my $DB_PASS = 'masterkey';

my ($dbhost, $dbname) = split ':', $dsn;

my $db = "dbi:InterBase:db=$dbname;host=$dbhost;ib_dialect=3";

my $dbi = DBI->connect($db, $DB_USER, $DB_PASS, { PrintError => 0,
                                                  RaiseError => 0,
                                                  AutoCommit => 1 })
    or die "FATAL ERROR: DBI->connect to $dsn failed";

# Counter for events.
my $want_events = 0;

# -----------------------------------------------------
# Event callback function
# -----------------------------------------------------
sub handle_event {
    my $pe = shift;

    while (my ($k, $v) = each %$pe) {
        print "Got event $k\n";
    }
    $want_events--;
    1;
}

my $station = 1;
my $curr_date = mktime(0, 0, 0, 1, 0, 110);  # 01 Jan 2010 @00:00
my $end_date = mktime(0, 0, 0, 1, 0, 111);   # 01 Jan 2011 @00:00

my $sql;

my $ev1 = "";
my $ev2 = "";

while ($curr_date < $end_date) {

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime($curr_date);

    my $dd = strftime ('%F', localtime($curr_date));
    my $hh = sprintf ('%.2d', $hour);
    my $tt = "${hh}:000:00.00";

    # Only using one here.  Kylix test program (and real application) 
    # use both of these, so this script registers for both.
    $ev1 = "PLAYLIST_INSERTED_${station}_${dd}_${hh}";
    $ev2 = "PLAYLIST_DELETED_${station}_${dd}_${hh}";

    my $evh = $dbi->func($ev1, $ev2, 'ib_init_event');

    # Set the callback
    $dbi->func($evh, \&handle_event, 'ib_register_callback');

    $want_events = 1;
    $sql = "execute procedure insert_log_entry (?, ?, ?, ?, ?, ?)";
    my $sth = $dbi->prepare($sql);

    my $res = $sth->execute($station, $dd, $tt, 'Event Test Entry', 0, 'N');

    print "Inserted $dd $hh\n";

    $sth->finish;

    while ($want_events > 0) {
        sleep 1;
    }

    $dbi->func($evh, 'ib_cancel_callback');

    # Bump to next hour and repeat
    $curr_date += 3600;

}

$dbi->disconnect;


When I run the above perl, I get this as output:


~ $perl event_test.pl "serv1-0000:event_fail"
Inserted 2010-01-01 00
Got event PLAYLIST_INSERTED_1_2010-01-01_00
Inserted 2010-01-01 01
Got event PLAYLIST_INSERTED_1_2010-01-01_01
............much elided.....
Inserted 2010-01-13 17
Got event PLAYLIST_INSERTED_1_2010-01-13_17
Inserted 2010-01-13 18
Got event PLAYLIST_INSERTED_1_2010-01-13_18
DBD::InterBase::db::ib_register_callback() -- ev is not a blessed SV reference 
at event_test.pl line 91.
Can't call method "execute" on an undefined value at event_test.pl line 97.
Broken pipe

and over on the server is another instance of terminating abnormally.

Things I've tried:

a). Making the event names shorter as in PI_{date}_{hour}

b). Table modification to store hour as an integer value and having the trigger 
use that instead of calling on substring.

Both of those changes were for naught.


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://tracker.firebirdsql.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to