[PATCH] Fix memory leak of reply_message in walreceiver

  • Jump to comment-1
    DaeMyung Kang<charsyam@gmail.com>
    Apr 26, 2026, 5:01 PM UTC
    Hi, Hackers,
    While reading walreceiver.c, I noticed that the static StringInfoData
    reply_message gets initialized inside the outer streaming loop in
    WalReceiverMain(), specifically right after walrcv_startstreaming()
    succeeds:
    
      /* Initialize LogstreamResult and buffers for processing messages */
      LogstreamResult.Write = LogstreamResult.Flush = GetXLogReplayRecPtr(NULL);
      initStringInfo(&reply_message);
    
    initStringInfo() unconditionally allocates a fresh ~1KB buffer with
    palloc() and overwrites the existing data pointer without freeing the
    previous one. So every time the walreceiver re-enters the streaming
    path -- e.g., after a timeline switch, end-of-WAL, or any other
    condition that drives the outer for(;;) loop to iterate -- the prior
    buffer is leaked. The leak is bounded per streaming restart but
    accumulates over the lifetime of a long-running standby that
    restarts streaming often.
    
    Subsequent uses of reply_message already call resetStringInfo() to
    reuse the buffer, so a single one-time initialization before the
    outer loop is sufficient. The attached patch moves the call up and
    adjusts the comment accordingly.
    
    This appears to date back to commit add6c3179a4 ("Make the streaming
    replication protocol messages architecture-independent.", 2012), so
    the fix is likely a candidate for back-patching to all supported
    branches.
    
    No new tests are added; the fix only releases resources and does not
    change observable behavior. `make check` and the streaming replication
    TAP test (src/test/recovery/t/001_stream_rep.pl) pass with the patch
    applied.
    
    Patch attached.
    
    Regards,
    DaeMyung Kang
    • Jump to comment-1
      Michael Paquier<michael@paquier.xyz>
      Apr 27, 2026, 12:47 AM UTC
      On Mon, Apr 27, 2026 at 01:59:09AM +0900, DaeMyung Kang wrote:
      initStringInfo() unconditionally allocates a fresh ~1KB buffer with
      palloc() and overwrites the existing data pointer without freeing the
      previous one. So every time the walreceiver re-enters the streaming
      path -- e.g., after a timeline switch, end-of-WAL, or any other
      condition that drives the outer for(;;) loop to iterate -- the prior
      buffer is leaked. The leak is bounded per streaming restart but
      accumulates over the lifetime of a long-running standby that
      restarts streaming often.
      This is a problem similar to [1], and I'd agree about cleaning that up
      properly.
      This appears to date back to commit add6c3179a4 ("Make the streaming
      replication protocol messages architecture-independent.", 2012), so
      the fix is likely a candidate for back-patching to all supported
      branches.
      This is minor, so I don't really see a point in back-patching. Same
      reason as the other thread.
      I'll go merge that together.
      [1]: https://www.postgresql.org/message-id/ae6vp9L-GUb0ERTF@paquier.xyz
      --
      Michael