<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur" -->

---
title: Memory safety for Postgres extensions in C/C++ | daily.dev
description: ClickHouse engineers detail how their four Postgres extensions (pg_clickhouse, pg_re2, pg_chdb, pg_stat_ch) each handle the fundamental incompatibility between...
canonical: https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Memory safety for Postgres extensions in C/C++ | daily.dev
og:description: ClickHouse engineers detail how their four Postgres extensions (pg_clickhouse, pg_re2, pg_chdb, pg_stat_ch) each handle the fundamental incompatibility between...
og:url: https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur
og:image: https://api.daily.dev/og/posts/H18ErYLuR.png
og:image:alt: Memory safety for Postgres extensions in C/C++
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory safety for Postgres extensions in C/C++

**[ClickHouse](https://daily.dev/sources/clickhouse)** · 5 min read · 33 upvotes · 2 comments

## Summary

ClickHouse engineers detail how their four Postgres extensions (pg_clickhouse, pg_re2, pg_chdb, pg_stat_ch) each handle the fundamental incompatibility between Postgres's C-based MemoryContext/setjmp-longjmp error handling and C++'s exception/destructor model. Mixing longjmp with nontrivial C++ destructors is undefined behavior, and uncaught exceptions crash the Postgres postmaster. Strategies range from eliminating C++ entirely (pg_clickhouse rewritten in C), scoping C++ tightly with local try/catch (pg_re2), isolating C++ runtimes in separate helper executables outside Postgres's process management (pg_chdb), to routing uncaught exceptions through ereport(FATAL) via a terminate handler in a background worker (pg_stat_ch). A real double-free bug found while writing the piece was fixed in a linked PR, with further isolation planned.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://clickhouse.com/blog/memory-safety-postgres-extensions-c-cpp>

## Questions this post answers

### Why is it unsafe to mix C++ exceptions with Postgres's setjmp/longjmp error handling?

Postgres uses setjmp/longjmp for its PG_TRY/PG_CATCH error handling, and jumping past a C++ object with a nontrivial destructor via longjmp is undefined behavior, not merely a resource leak. C++ exceptions also bypass PG_CATCH/PG_FINALLY entirely, and an uncaught exception aborts the process, forcing the Postgres postmaster to restart everything for fear shared memory is corrupted.

_daily.dev surfaces engineering writeups like this for developers building safe C/C++ Postgres extensions._

### How does isolating a C++ library in a separate helper process protect a Postgres extension from crashes?

Running libraries like libchdb in a separate helper executable, forked and exec'd by the backend, keeps their C++ runtime, threads, allocations, and failures outside the Postgres backend or background worker process. A crash in the helper then fails only the calling operation instead of triggering full Postgres cluster crash recovery, since the helper is a descendant of postmaster but not managed as one of its background workers.

_Developers isolating risky native code from a database process can track approaches like this on daily.dev._

### How can a Postgres background worker convert an uncaught C++ exception into a safe process exit instead of a crash?

A process-wide terminate handler can route std::terminate and uncaught exceptions through ereport(FATAL) instead of the default abort()/SIGABRT. Postgres treats FATAL exit as non-crash if shared-memory detachment completes cleanly, letting the worker restart per bgw_restart_time instead of triggering cluster-wide crash recovery that disconnects other sessions.

_daily.dev helps engineers hardening database extensions keep up with patterns like this._

## Community discussion

Top comments from developers on daily.dev.

**@agustinbarrientos** · 0 upvotes

> How much latency does the helper add for small queries? A persistent helper sounds appealing if startup is a big fraction of query time.

**@ristotoldsep** · 0 upvotes

> C++ destructors meeting Postgres longjmp is a horror story in one sentence. Good write-up.

## Similar posts on daily.dev

- [pg\_clickhouse 0.3.1: Now With More C](https://daily.dev/posts/pg-clickhouse-0-3-1-now-with-more-c-h3naoiqtg) · Planet PostgreSQL · 1 upvotes · 0 comments
- [Can your Postgres survive a bad query?](https://daily.dev/posts/can-your-postgres-survive-a-bad-query--sdf4kdxbn) · ClickHouse · 7 upvotes · 1 comments
- [Uncaught Exceptions in C\+\+](https://daily.dev/posts/uncaught-exceptions-in-c--9zdrjnh7f) · Jacek Galowicz · 0 upvotes · 0 comments
- [The four horsemen behind thousands of Postgres outages](https://daily.dev/posts/the-four-horsemen-behind-thousands-of-postgres-outages-tu19ush18) · Hacker News · 2 upvotes · 1 comments

---

Tags: [#postgresql](https://daily.dev/tags/postgresql), [#c++](https://daily.dev/tags/c++), [#clickhouse](https://daily.dev/tags/clickhouse)

[View this post on daily.dev](https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Memory safety for Postgres extensions in C/C++","url":"https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur"},"datePublished":"2026-09-30T14:00:38.920Z","dateModified":"2026-09-30T14:21:16.380Z","description":"ClickHouse engineers detail how their four Postgres extensions (pg_clickhouse, pg_re2, pg_chdb, pg_stat_ch) each handle the fundamental incompatibility between...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/f8ac24db7c8518a449df1c4bc6585e0d?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/f8ac24db7c8518a449df1c4bc6585e0d?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"ClickHouse","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"ClickHouse","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/clickhouse","url":"https://daily.dev/sources/clickhouse"},"commentCount":2,"discussionUrl":"https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":33},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":2}],"keywords":"postgresql,c++,clickhouse","timeRequired":"PT5M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"ClickHouse","item":"https://daily.dev/sources/clickhouse"},{"@type":"ListItem","position":3,"name":"Memory safety for Postgres extensions in C/C++"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur","comment":[{"@type":"Comment","text":"How much latency does the helper add for small queries? A persistent helper sounds appealing if startup is a big fraction of query time.","datePublished":"2026-10-02T00:24:51.852Z","url":"https://daily.dev/posts/H18ErYLuR#c-frwHyBO9Q","author":{"@type":"Person","name":"Agustin Barrientos","url":"https://daily.dev/agustinbarrientos","image":"https://media.daily.dev/image/upload/s--5ayxQnqn--/f_auto/v1788281802/avatars/avatar_wQYYVe5Tbj0NJ7C7qPoa8?_a=BAMAMicg0"}},{"@type":"Comment","text":"C++ destructors meeting Postgres longjmp is a horror story in one sentence. Good write-up.","datePublished":"2026-10-02T11:41:05.994Z","url":"https://daily.dev/posts/H18ErYLuR#c-bMn4IhcMM","author":{"@type":"Person","name":"Risto Tõldsep","url":"https://daily.dev/ristotoldsep","image":"https://lh3.googleusercontent.com/a/ACg8ocLDWc6mZn0JwNmXXw6WY0L_HJ6pegzRttooC5VgtXESHSj3MNYx=s96-c"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/memory-safety-for-postgres-extensions-in-c-c--h18erylur#faq","mainEntity":[{"@type":"Question","name":"Why is it unsafe to mix C++ exceptions with Postgres's setjmp/longjmp error handling?","acceptedAnswer":{"@type":"Answer","text":"Postgres uses setjmp/longjmp for its PG_TRY/PG_CATCH error handling, and jumping past a C++ object with a nontrivial destructor via longjmp is undefined behavior, not merely a resource leak. C++ exceptions also bypass PG_CATCH/PG_FINALLY entirely, and an uncaught exception aborts the process, forcing the Postgres postmaster to restart everything for fear shared memory is corrupted. daily.dev surfaces engineering writeups like this for developers building safe C/C++ Postgres extensions."}},{"@type":"Question","name":"How does isolating a C++ library in a separate helper process protect a Postgres extension from crashes?","acceptedAnswer":{"@type":"Answer","text":"Running libraries like libchdb in a separate helper executable, forked and exec'd by the backend, keeps their C++ runtime, threads, allocations, and failures outside the Postgres backend or background worker process. A crash in the helper then fails only the calling operation instead of triggering full Postgres cluster crash recovery, since the helper is a descendant of postmaster but not managed as one of its background workers. Developers isolating risky native code from a database process can track approaches like this on daily.dev."}},{"@type":"Question","name":"How can a Postgres background worker convert an uncaught C++ exception into a safe process exit instead of a crash?","acceptedAnswer":{"@type":"Answer","text":"A process-wide terminate handler can route std::terminate and uncaught exceptions through ereport(FATAL) instead of the default abort()/SIGABRT. Postgres treats FATAL exit as non-crash if shared-memory detachment completes cleanly, letting the worker restart per bgw_restart_time instead of triggering cluster-wide crash recovery that disconnects other sessions. daily.dev helps engineers hardening database extensions keep up with patterns like this."}}]}
```

