PostgreSQL Source Code: src/backend/storage/lmgr/deadlock.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

27

35

36

37

38

39

40

41

42

43

44

45

46

47typedef struct

48{

49 PGPROC *waiter;

50 PGPROC *blocker;

51 LOCK *lock;

52 int pred;

53 int link;

55

56

57typedef struct

58{

59 LOCK *lock;

60 PGPROC **procs;

63

64

65

66

67

68

69

70

71

72typedef struct

73{

76 int pid;

78

79

83 EDGE *softEdges, int *nSoftEdges);

85 EDGE *softEdges, int *nSoftEdges);

87 PGPROC *checkProcLeader,

88 int depth, EDGE *softEdges, int *nSoftEdges);

90static bool TopoSort(LOCK *lock, EDGE *constraints, int nConstraints,

92

93#ifdef DEBUG_DEADLOCK

94static void PrintLockQueue(LOCK *lock, const char *info);

95#endif

96

97

98

99

100

101

102

105

106

110

111

115

116

120

121

127

128

130

131

132

133

134

135

136

137

138

139

140

141

142

143void

145{

147

148

150

151

152

153

154

157

158

159

160

161

165

166

167

168

169

170

171

175

176

177

178

179

180

181

182

183

186

187

188

189

190

191

192

193

194

196 "MAX_BACKENDS_BITS too big for * 4");

200

202}

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

221{

222

226

227

229

230

232 {

233

234

235

236

237 int nSoftEdges;

238

239 TRACE_POSTGRESQL_DEADLOCK_FOUND();

240

243 elog(FATAL, "deadlock seems to have disappeared");

244

245 return DS_HARD_DEADLOCK;

246 }

247

248

250 {

255

257

258#ifdef DEBUG_DEADLOCK

259 PrintLockQueue(lock, "DeadLockCheck:");

260#endif

261

262

264 for (int j = 0; j < nProcs; j++)

266

267#ifdef DEBUG_DEADLOCK

268 PrintLockQueue(lock, "rearranged to:");

269#endif

270

271

273 }

274

275

280 else

282}

283

284

285

286

287

288

291{

293

296

297 return ptr;

298}

299

300

301

302

303

304

305

306

307

308

309

310

311static bool

313{

314 int nEdges;

315 int oldPossibleConstraints;

316 bool savedList;

317 int i;

318

320 if (nEdges < 0)

321 return true;

322 if (nEdges == 0)

323 return false;

325 return true;

328 {

329

331 savedList = true;

332 }

333 else

334 {

335

336 savedList = false;

337 }

338

339

340

341

342 for (i = 0; i < nEdges; i++)

343 {

344 if (!savedList && i > 0)

345 {

346

348 elog(FATAL, "inconsistent results during deadlock check");

349 }

354 return false;

355

357 }

359 return true;

360}

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377static int

379{

380 int softFound = 0;

382 int nSoftEdges;

383 int i;

384

385

386

387

389 return -1;

390

391

392

393

394

396 return -1;

397

398

399

400

401

402

404 {

406 {

407 if (nSoftEdges == 0)

408 return -1;

409 softFound = nSoftEdges;

410 }

412 {

413 if (nSoftEdges == 0)

414 return -1;

415 softFound = nSoftEdges;

416 }

417 }

418 if (FindLockCycle(startProc, softEdges, &nSoftEdges))

419 {

420 if (nSoftEdges == 0)

421 return -1;

422 softFound = nSoftEdges;

423 }

424 return softFound;

425}

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445static bool

447 EDGE *softEdges,

448 int *nSoftEdges)

449{

452 *nSoftEdges = 0;

454}

455

456static bool

458 int depth,

459 EDGE *softEdges,

460 int *nSoftEdges)

461{

462 int i;

464

465

466

467

468

471

472

473

474

476 {

478 {

479

480 if (i == 0)

481 {

482

483

484

485

488

489 return true;

490 }

491

492

493

494

495

496 return false;

497 }

498 }

499

502

503

504

505

506

507 if (checkProc->links.next != NULL && checkProc->waitLock != NULL &&

509 nSoftEdges))

510 return true;

511

512

513

514

515

516

517

518

520 {

522

524

525 if (memberProc->links.next != NULL && memberProc->waitLock != NULL &&

526 memberProc != checkProc &&

528 nSoftEdges))

529 return true;

530 }

531

532 return false;

533}

534

535static bool

537 PGPROC *checkProcLeader,

538 int depth,

539 EDGE *softEdges,

540 int *nSoftEdges)

541{

546 int conflictMask;

547 int i;

548 int numLockModes,

549 lm;

550

551

552

553

554

555

557 return false;

558

560 numLockModes = lockMethodTable->numLockModes;

562

563

564

565

566

568 {

571

574

575

576 if (leader != checkProcLeader)

577 {

578 for (lm = 1; lm <= numLockModes; lm++)

579 {

582 {

583

585 softEdges, nSoftEdges))

586 {

587

589

592 info->pid = checkProc->pid;

593

594 return true;

595 }

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619 if (checkProc == MyProc &&

622

623

624 break;

625 }

626 }

627 }

628 }

629

630

631

632

633

634

635

636

637

638

640 {

642 break;

643 }

644

646 {

647

650

651 for (i = 0; i < queue_size; i++)

652 {

654

655 proc = procs[i];

658

659

660

661

662

663

664

665

666 if (leader == checkProcLeader)

667 break;

668

669

671 {

672

674 softEdges, nSoftEdges))

675 {

676

678

681 info->pid = checkProc->pid;

682

683

684

685

687 softEdges[*nSoftEdges].waiter = checkProcLeader;

688 softEdges[*nSoftEdges].blocker = leader;

689 softEdges[*nSoftEdges].lock = lock;

690 (*nSoftEdges)++;

691 return true;

692 }

693 }

694 }

695 }

696 else

697 {

698 PGPROC *lastGroupMember = NULL;

701

702

704

705

706

707

708

709

710

711

713 lastGroupMember = checkProc;

714 else

715 {

717 {

719

721 lastGroupMember = proc;

722 }

723 Assert(lastGroupMember != NULL);

724 }

725

726

727

728

730 {

732

734

737

738

739 if (proc == lastGroupMember)

740 break;

741

742

744 leader != checkProcLeader)

745 {

746

748 softEdges, nSoftEdges))

749 {

750

752

755 info->pid = checkProc->pid;

756

757

758

759

761 softEdges[*nSoftEdges].waiter = checkProcLeader;

762 softEdges[*nSoftEdges].blocker = leader;

763 softEdges[*nSoftEdges].lock = lock;

764 (*nSoftEdges)++;

765 return true;

766 }

767 }

768 }

769 }

770

771

772

773

774 return false;

775}

776

777

778

779

780

781

782

783

784

785

786

787

788

789static bool

791 int nConstraints)

792{

793 int nWaitOrderProcs = 0;

794 int i,

795 j;

796

798

799

800

801

802

803

804 for (i = nConstraints; --i >= 0;)

805 {

806 LOCK *lock = constraints[i].lock;

807

808

810 {

812 break;

813 }

814 if (j >= 0)

815 continue;

816

822

823

824

825

826

827 if (TopoSort(lock, constraints, i + 1,

829 return false;

831 }

832 return true;

833}

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861static bool

863 EDGE *constraints,

864 int nConstraints,

865 PGPROC **ordering)

866{

870 int i,

871 j,

872 jj,

873 k,

874 kk,

875 last;

877

878

879 i = 0;

881 {

884 }

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

909 for (i = 0; i < nConstraints; i++)

910 {

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925 proc = constraints[i].waiter;

926 Assert(proc != NULL);

927 jj = -1;

928 for (j = queue_size; --j >= 0;)

929 {

931

933 {

935 if (jj == -1)

936 jj = j;

937 else

938 {

941 }

942 }

943 }

944

945

946 if (jj < 0)

947 continue;

948

949

950

951

952

953

954 proc = constraints[i].blocker;

955 Assert(proc != NULL);

956 kk = -1;

957 for (k = queue_size; --k >= 0;)

958 {

960

962 {

964 if (kk == -1)

965 kk = k;

966 else

967 {

970 }

971 }

972 }

973

974

975 if (kk < 0)

976 continue;

977

980

981 constraints[i].pred = jj;

984 }

985

986

987

988

989

990

991

992

993

994

995

996

997 last = queue_size - 1;

998 for (i = queue_size - 1; i >= 0;)

999 {

1000 int c;

1001 int nmatches = 0;

1002

1003

1005 last--;

1006 for (j = last; j >= 0; j--)

1007 {

1009 break;

1010 }

1011

1012

1013 if (j < 0)

1014 return false;

1015

1016

1017

1018

1019

1020

1021

1022

1023

1024

1028 Assert(proc != NULL);

1029 for (c = 0; c <= last; ++c)

1030 {

1032 topoProcs[c]->lockGroupLeader == proc))

1033 {

1036 ++nmatches;

1037 }

1038 }

1039 Assert(nmatches > 0);

1040 i -= nmatches;

1041

1042

1045 }

1046

1047

1048 return true;

1049}

1050

1051#ifdef DEBUG_DEADLOCK

1052static void

1053PrintLockQueue(LOCK *lock, const char *info)

1054{

1057

1058 printf("%s lock %p queue ", info, lock);

1059

1061 {

1063

1065 }

1068}

1069#endif

1070

1071

1072

1073

1074void

1076{

1077 StringInfoData clientbuf;

1078 StringInfoData logbuf;

1080 int i;

1081

1085

1086

1088 {

1090 int nextpid;

1091

1092

1094 nextpid = info[1].pid;

1095 else

1097

1098

1100

1102

1103 if (i > 0)

1105

1107 _("Process %d waits for %s on %s; blocked by process %d."),

1108 info->pid,

1111 locktagbuf.data,

1112 nextpid);

1113 }

1114

1115

1117

1118

1120 {

1122

1124

1126 _("Process %d: %s"),

1127 info->pid,

1129 }

1130

1132

1135 errmsg("deadlock detected"),

1138 errhint("See server log for query details.")));

1139}

1140

1141

1142

1143

1144

1145

1146void

1151{

1153

1156 info->pid = proc1->pid;

1157 info++;

1160 info->pid = proc2->pid;

1162}

const char * pgstat_get_backend_current_activity(int pid, bool checkUser)

#define MemSet(start, val, len)

#define StaticAssertStmt(condition, errmessage)

static bool TopoSort(LOCK *lock, EDGE *constraints, int nConstraints, PGPROC **ordering)

static int TestConfiguration(PGPROC *startProc)

static WAIT_ORDER * waitOrders

static bool FindLockCycleRecurseMember(PGPROC *checkProc, PGPROC *checkProcLeader, int depth, EDGE *softEdges, int *nSoftEdges)

static bool FindLockCycle(PGPROC *checkProc, EDGE *softEdges, int *nSoftEdges)

static int maxPossibleConstraints

static bool DeadLockCheckRecurse(PGPROC *proc)

PGPROC * GetBlockingAutoVacuumPgproc(void)

static EDGE * possibleConstraints

static PGPROC ** waitOrderProcs

void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)

static PGPROC ** visitedProcs

static bool ExpandConstraints(EDGE *constraints, int nConstraints)

static int * beforeConstraints

static int nDeadlockDetails

void DeadLockReport(void)

static int * afterConstraints

static DEADLOCK_INFO * deadlockDetails

static int maxCurConstraints

void InitDeadLockChecking(void)

static int nCurConstraints

DeadLockState DeadLockCheck(PGPROC *proc)

static PGPROC * blocking_autovacuum_proc

static EDGE * curConstraints

static int nPossibleConstraints

static bool FindLockCycleRecurse(PGPROC *checkProc, int depth, EDGE *softEdges, int *nSoftEdges)

static PGPROC ** topoProcs

int errdetail_internal(const char *fmt,...)

int errhint(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

int errdetail_log(const char *fmt,...)

#define ereport(elevel,...)

Assert(PointerIsAligned(start, uint64))

#define dlist_foreach(iter, lhead)

static void dclist_push_tail(dclist_head *head, dlist_node *node)

static uint32 dclist_count(const dclist_head *head)

static void dclist_init(dclist_head *head)

#define dlist_container(type, membername, ptr)

#define dclist_foreach(iter, lhead)

void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)

const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)

LockMethod GetLocksMethodTable(const LOCK *lock)

#define LOCK_LOCKTAG(lock)

@ LOCKTAG_RELATION_EXTEND

@ DS_BLOCKED_BY_AUTOVACUUM

#define LOCKBIT_ON(lockmode)

MemoryContext TopMemoryContext

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

#define ERRCODE_T_R_DEADLOCK_DETECTED

void pgstat_report_deadlock(void)

#define PROC_IS_AUTOVACUUM

#define MAX_BACKENDS_BITS

void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)

void resetStringInfo(StringInfo str)

void appendStringInfo(StringInfo str, const char *fmt,...)

void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)

void appendStringInfoChar(StringInfo str, char ch)

void initStringInfo(StringInfo str)

uint8 locktag_lockmethodid

const LOCKMASK * conflictTab

dlist_head lockGroupMembers

static struct link * links