Re:Re: some question about _bt_getbuf

From: "Imai, Yoshikazu" <imai(dot)yoshikazu(at)jp(dot)fujitsu(dot)com>
To: '自己' <zoulx1982(at)163(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>, Simon Riggs <simon(at)2ndquadrant(dot)com>
Subject: Re:Re: some question about _bt_getbuf
Date: 2018-06-26 08:09:18
Message-ID: 0F97FA9ABBDBE54F91744A9B37151A5116E4DD@g01jpexmbkw24
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

> At 2018-05-15 01:49:41, "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:
> >=?GBK?B?19S8ug==?= <zoulx1982(at)163(dot)com> writes:
> >> i run test using pg10.0 on my machine, and the program crashed on _bt_getbuf.
> >> And i found the following code:
> >> the routine _bt_page_recyclable say maybe the page is all-zero page,
> >> if so then the code run (BTPageOpaque) PageGetSpecialPointer(page);
> >> it will be failed because it access invalid memory.
> >> I don't know whether it is so. Look forward t your reply, thanks.
> >
> >This code's clearly broken, as was discussed before:
> >
> >https://www.postgresql.org/message-id/flat/2628.1474272158%40localhost
> >
> >but nothing was done about it, perhaps partly because we didn't have a
> >reproducible test case. Do you have one?
> >
> > regards, tom lane
>
> Unfortunately, I don't have a complete test case.

I recently checked about this code and previous discussion and tried to occur a crash.
I will describe how to occur a crash in the last of this mail, but I don't know whether it is useful because I used gdb to occur a crash, that it is not actually a reproducible test case.

As was discussed before, this crash happens when recycling an all-zeroes page in an index.
Referring to below comments in code, an all-zeroes page is created when backend downs in the split process after extending the index's relation to get a new page and before making WAL entries for that.

bool
_bt_page_recyclable(Page page)
{
BTPageOpaque opaque;

/*
* It's possible to find an all-zeroes page in an index --- for example, a
* backend might successfully extend the relation one page and then crash
* before it is able to make a WAL entry for adding the page. If we find a
* zeroed page then reclaim it.
*/
if (PageIsNew(page))
return true;
...
}

After backend down at that time, an extended new page is not initialized since a recovery process after a backend down do nothing because of no WAL entry about a new page, and it will be recyclable when vacuum runs.

Considering above conditions, I reproduced a crash as below.
I tested at version in master(11beta1), compiled with --enable-cassert and --enable-debug, with hot-standby.

<<method for making recyclable new page>>
(psql) CREATE TABLE mytab (id int, val int);
(psql) CREATE INDEX idx_val ON mytab(val);
(gdb) b nbtinsert.c:1467 (at XLogBeginInsert(); in _bt_split())
(gdb) c
while(breakpoint is not hit){
(psql) INSERT INTO mytab SELECT t, t FROM generate_series(1, 3000) t;
}
[bash] kill -s SIGKILL (backend pid)
(psql) VACUUM;

<<method for occuring a crash>>
while(crash is not occurred){
(psql) INSERT INTO mytab SELECT t, t FROM generate_series(1, 3000) t;
}

Yoshikazu Imai

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Chen, Yan-Jack (NSB - CN/Hangzhou) 2018-06-26 08:12:56 RE: "wal receiver" process hang in syslog() while exiting after receiving SIGTERM while the postgres has been promoted.
Previous Message Amit Langote 2018-06-26 07:57:53 Re: partition tree inspection functions