ctm / mb2-doc

Mb2, poker software
https://devctm.com
7 stars 2 forks source link

Ring Game crash #532

Closed ctm closed 3 years ago

ctm commented 3 years ago

During devctm.com's first ring game, mb2 coughed up this:

2021-03-05T23:32:23.011071727Z thread '<unnamed>' panicked at 'attempt to subtract with overflow', mb2/src/table.rs:3788:17
2021-03-05T23:32:23.011137617Z stack backtrace:
...
2021-03-05T23:32:23.900417822Z   16:     0x55ee49d8094d - <mb2::table::Table as mb2::table::UserActions>::quit::h1d802eab260eeb49
2021-03-05T23:32:23.928158753Z   17:     0x55ee49f1aee8 - mb2::tournament::RunningEvent::process_user_request::h57744c436593a1d5
2021-03-05T23:32:23.928180153Z                                at /usr/src/poker/mb2/src/tournament.rs:1425:17
2021-03-05T23:32:23.928410175Z   18:     0x55ee49f1aee8 - mb2::tournament::RunningEvent::process::hfc0bae7ba2c135cf
2021-03-05T23:32:23.928421805Z                                at /usr/src/poker/mb2/src/tournament.rs:1363:37
2021-03-05T23:32:23.930921641Z   19:     0x55ee49f12515 - mb2::tournament::RunningEvent::run::h2bf25d9d40dcc15d
2021-03-05T23:32:23.930961812Z                                at /usr/src/poker/mb2/src/tournament.rs:585:49
2021-03-05T23:32:23.940477012Z   20:     0x55ee49d392f6 - mb2::tournament::RunningEvent::start::{{closure}}::h91cbd85d0be7aaa3
2021-03-05T23:32:23.940539722Z                                at /usr/src/poker/mb2/src/tournament.rs:547:31

The code in question:

        if !between_hands && !folded {
            self.n_not_folded -= 1;
            if !all_in {
                self.n_not_all_in -= 1;
            }
        }

Specifically, it's dying on the self.n_not_all_in -= 1; line. One possibility is that between_hands is false even though logically we're between hands.

If I slog through the database and pay attention to timestamps I should be able to figure out what happened. If so, there's probably a trivial fix. The biggest question is which of the two of us (deadhead or AIYAH❗ quit.

ctm commented 3 years ago

FWIW, it was AIYAH❗'s quit that killed mb2:

 1509253 | 2021-03-05 23:32:23.006526+00 |       1 | "Quit"                                    | 5954359414818829181 | 2021-03-05 23:32:23.008174+00

I know the above session id is his. My quit came in earlier:

 1509248 | 2021-03-05 23:30:46.380184+00 |       1 | "Quit"                                    | 2966088904328274233 | 2021-03-05 23:30:46.380475+00

so it's quite possible that my quit "worked". I don't see an entry in pay_outs for me, but the rule might be that people with no chips get no pay_outs. I do see that my players row was not updated after I quit, but again that might be because I quit with 0 chips:

mb2=> select * from pay_outs order by id desc limit 1;
select * from pay_outs order by id desc limit 1;
  id  | event_id | player_id | rank | pay_out |          created_at           
------+----------+-----------+------+---------+-------------------------------
 2221 |     1922 |         6 |    1 |     550 | 2021-03-05 05:46:43.446539+00

mb2=> select updated_at from players where id = 10;
select updated_at from players where id = 10;
          updated_at           
-------------------------------
 2021-03-05 23:13:26.047875+00
(1 row)

At this point, it probably makes sense to just try to recreate the situation locally. I think it's probably just a matter of two players start, one (the better, smarter and more good looking!) wins. The other quits (perhaps it matters that the quitter closes his table first, but it probably doesn't) and then the winner quits.

My guess is I can reproduce it trivially, in which case I can add some instrumentation and figure out exactly what is happening. However, this evening's tournament starts in a half hour, so I might not get this finished by then.

ctm commented 3 years ago

I'm an idiot:

    fn begin_hand(&mut self) {
        self.between_hands = false;
...
        if self.n_players_in_next_hand() < 2 {
            self.paused_due_to_too_few_players = true;
            self.table_message(TableMessage::PausedTooFewPlayers);
            self.send_status(None);
            return;
        }

I could have saved a lot of time by just glancing at the code before writing up this issue. Oh well. I may be able to deploy my fix before this evening's game, but it will be close.

ctm commented 3 years ago

Deploying now.