Thread: some question about _bt_getbuf

some question about _bt_getbuf

From
自己
Date:
Hi,
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.

                                if (_bt_page_recyclable(page))
{
/*
* If we are generating WAL for Hot Standby then create a
* WAL record that will allow us to conflict with queries
* running on standby.
*/
if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
{
                                                BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);  /* if page is all-zero, this will failed */
_bt_log_reuse_page(rel, blkno, opaque->btpo.xact);
}

/* Okay to use page.  Re-initialize and return it */
_bt_pageinit(page, BufferGetPageSize(buf));
return buf;
}



 

Re: some question about _bt_getbuf

From
Tom Lane
Date:
=?GBK?B?19S8ug==?= <zoulx1982@163.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


Re:Re: some question about _bt_getbuf

From
自己
Date:
At 2018-05-15 01:49:41, "Tom Lane" <tgl@sss.pgh.pa.us> wrote:
>自己 <zoulx1982@163.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 run regress test and tpmc test using benchmarksql on the same database instance.
Of course, they run in different database, regress run in regression and tpmc run in postgres.
the following is the backtrace:

#0 0x00007f0a973c61d7 in raise () from /lib64/libc.so.6 #1 0x00007f0a973c78c8 in abort () from /lib64/libc.so.6 #2 0x0000000000b77c91 in ExceptionalCondition (conditionName=0xe2f238 "!(((PageHeader) (page))->pd_special >= (__builtin_offsetof (PageHeaderData, pd_linp)))", errorType=0xe2f1ca "FailedAssertion", fileName=0xe2f1a0 "../../../../src/include/storage/bufpage.h", lineNumber=315) at assert.c:54 #3 0x0000000000691292 in PageValidateSpecialPointer (page=0x7f0a7ecb4800 "") at ../../../../src/include/storage/bufpage.h:315 #4 0x00000000006927e2 in _bt_getbuf (rel=0x7f0a98e8d4c0, blkno=13, access=2) at nbtpage.c:641 #5 0x000000000068cda8 in _bt_split (rel=0x7f0a98e8d4c0, buf=15974, cbuf=0, firstright=279, newitemoff=298, newitemsz=24, newitem=0x24e7178, newitemonleft=0 '\000') at nbtinsert.c:1017 #6 0x000000000068c465 in _bt_insertonpg (rel=0x7f0a98e8d4c0, buf=15974, cbuf=0, stack=0x24e7520, itup=0x24e7178, newitemoff=298, split_only_page=0 '\000') at nbtinsert.c:809 #7 0x000000000068b146 in _bt_doinsert (rel=0x7f0a98e8d4c0, itup=0x24e7178, checkUnique=UNIQUE_CHECK_YES, heapRel=0x7f0a98e561c0) at nbtinsert.c:210 #8 0x0000000000697a8e in btinsert (rel=0x7f0a98e8d4c0, values=0x7ffe20e41450, isnull=0x7ffe20e41430 "", ht_ctid=0x24e71dc, heapRel=0x7f0a98e561c0, checkUnique=UNIQUE_CHECK_YES, indexInfo=0x24e6bd8) at nbtree.c:330 #9 0x0000000000689158 in index_insert (indexRelation=0x7f0a98e8d4c0, values=0x7ffe20e41450, isnull=0x7ffe20e41430 "", heap_t_ctid=0x24e71dc, heapRelation=0x7f0a98e561c0, checkUnique=UNIQUE_CHECK_YES, indexInfo=0x24e6bd8) at indexam.c:210 #10 0x000000000070d7bd in CatalogIndexInsert (indstate=0x24e64d0, heapTuple=0x24e71d8) at indexing.c:136 #11 0x000000000070d872 in CatalogTupleInsertWithInfo (heapRel=0x7f0a98e561c0, tup=0x24e71d8, indstate=0x24e64d0) at indexing.c:193 #12 0x0000000000703771 in InsertPgAttributeTuple (pg_attribute_rel=0x7f0a98e561c0, new_attribute=0x7ffe20e41700, indstate=0x24e64d0) at heap.c:639 #13 0x00000000007039aa in AddNewAttributeTuples (new_rel_oid=34538, tupdesc=0x7f0a98e71bb8, relkind=114 'r', oidislocal=0 '\000', oidinhcount=0) at heap.c:738 #14 0x0000000000704736 in heap_create_with_catalog (relname=0x7ffe20e41b90 "disappear", relnamespace=2200, reltablespace=0, relid=34538, reltypeid=0, reloftypeid=0, ownerid=10, tupdesc=0x2417310, cooked_constraints=0x0, relkind=114 'r', relpersistence=112 'p', shared_relation=0 '\000', mapped_relation=0 '\000', oidislocal=0 '\000', oidinhcount=0, oncommit=ONCOMMIT_NOOP, reloptions=0, use_user_acl=1 '\001', allow_system_table_mods=0 '\000', is_internal=0 '\000', typaddress=0x0) at heap.c:1276 #15 0x0000000000808ef4 in DefineRelation (stmt=0x2416e38, relkind=114 'r', ownerId=10, typaddress=0x0, queryString=0x2443860 "CREATE TABLE disappear (a int4);") at tablecmds.c:726 #16 0x0000000000a203ca in ProcessUtilitySlow (pstate=0x2416d20, pstmt=0x2444910, queryString=0x2443860 "CREATE TABLE disappear (a int4);", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2444a08, completionTag=0x7ffe20e42370 "") at utility.c:1008 #17 0x0000000000a20206 in standard_ProcessUtility (pstmt=0x2444910, queryString=0x2443860 "CREATE TABLE disappear (a int4);", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2444a08, completionTag=0x7ffe20e42370 "") at utility.c:928 #18 0x0000000000a1f36d in ProcessUtility (pstmt=0x2444910, queryString=0x2443860 "CREATE TABLE disappear (a int4);", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x2444a08, completionTag=0x7ffe20e42370 "") at utility.c:357 #19 0x0000000000a1e36e in PortalRunUtility (portal=0x249f2e0, pstmt=0x2444910, isTopLevel=1 '\001', setHoldSnapshot=0 '\000', dest=0x2444a08, completionTag=0x7ffe20e42370 "") at pquery.c:1190 #20 0x0000000000a1e582 in PortalRunMulti (portal=0x249f2e0, isTopLevel=1 '\001', setHoldSnapshot=0 '\000', dest=0x2444a08, altdest=0x2444a08, completionTag=0x7ffe20e42370 "") at pquery.c:1336 #21 0x0000000000a1dad1 in PortalRun (portal=0x249f2e0, count=9223372036854775807, isTopLevel=1 '\001', run_once=1 '\001', dest=0x2444a08, altdest=0x2444a08, completionTag=0x7ffe20e42370 "") at pquery.c:811 #22 0x0000000000a17b1b in exec_simple_query (query_string=0x2443860 "CREATE TABLE disappear (a int4);") at postgres.c:1100 #23 0x0000000000a1bce3 in PostgresMain (argc=1, argv=0x244e730, dbname=0x244e510 "regression",



 

Re:Re: some question about _bt_getbuf

From
"Imai, Yoshikazu"
Date:
Hi,

> At 2018-05-15 01:49:41, "Tom Lane" <tgl@sss.pgh.pa.us> wrote:
> >=?GBK?B?19S8ug==?= <zoulx1982@163.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
tooccur 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
extendingthe 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
donothing 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



Re: some question about _bt_getbuf

From
Kyotaro HORIGUCHI
Date:
Hello, thank you for reprising this thread.

This issue is technically disucssed in the thread Tom suggested
upthread.

https://www.postgresql.org/message-id/flat/2628.1474272158%40localhost

At Tue, 26 Jun 2018 08:09:18 +0000, "Imai, Yoshikazu" <imai.yoshikazu@jp.fujitsu.com> wrote in
<0F97FA9ABBDBE54F91744A9B37151A5116E4DD@g01jpexmbkw24>
> Hi,
> 
> > At 2018-05-15 01:49:41, "Tom Lane" <tgl@sss.pgh.pa.us> wrote:
> > >=?GBK?B?19S8ug==?= <zoulx1982@163.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
gdbto 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
extendingthe index's relation to get a new page and before making WAL entries for that.
 

I'm not sure if there's no other cases to create such pages but
at least your steps does as mentioned in the comment of
_bt_page_recyclable(). And I agree to Amit's diagnosis and Tom's
solution.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center