SERVICEFILE shows wrong file after servicefile fallback

First seen: 2026-06-02 13:42:23+00:00 · Messages: 1 · Participants: 1

Latest Update

2026-06-04 · claude-opus-4-6

SERVICEFILE Shows Wrong File After Servicefile Fallback

Core Problem

This bug report identifies a logical inconsistency in libpq's service file resolution mechanism, specifically in how the SERVICEFILE connection parameter tracks which file actually provided the service definition.

The Service File Fallback Mechanism

libpq supports a two-tier service file lookup:

  1. Primary lookup: The file specified via the servicefile connection parameter (or PGSERVICEFILE environment variable)
  2. Fallback lookup: If the requested service name is not found in the primary file, libpq falls back to the system-wide pg_service.conf (located in PGSYSCONFDIR)

This fallback is implemented in parseServiceFile() within libpq's connection handling code.

The Bug: State Desynchronization

The issue arises from commit 092f3c63efc6, which introduced the SERVICEFILE connection option to expose which service file was used. The problem is a classic state synchronization bug:

  1. User specifies servicefile=/tmp/svc/empty.conf in the connection string
  2. libpq stores this value in connOptions early during connection parameter parsing
  3. parseServiceFile() is called with the specified file — the requested service is not found
  4. libpq falls back to $PGSYSCONFDIR/pg_service.conf — the service is found here
  5. However, parseServiceFile() checks whether servicefile is already set in connection options, and if so, refuses to update it
  6. Result: connOptions.servicefile still points to the original (empty) file, not the file that actually provided the service configuration

This means SERVICEFILE (exposed as a psql variable) reports a file that did not contain the service definition — a misleading and incorrect value.

Architectural Significance

This matters because:

Proposed Fix

The fix is straightforward: when the fallback path is taken (i.e., the service is found in pg_service.conf rather than the originally-specified service file), explicitly update the servicefile connection option to reflect the actual file that provided the service definition.

This ensures that:

Design Consideration

The original guard in parseServiceFile() — "if servicefile is already set, don't update" — was likely intended to preserve the user's explicitly-specified value. However, this logic is incorrect in the fallback scenario: once the fallback succeeds, the "actual" service file has changed, and the connection option should reflect the truth rather than the user's initial (unsuccessful) specification.

Affected Code Path

libpq/fe-connect.c → connectOptions2() → parseServiceInfo() → parseServiceFile()

The flow:

  1. parseServiceFile(filename=user_specified_file, ...) → service not found, returns without applying settings
  2. parseServiceFile(filename=sysconf_file, ...) → service found, applies settings but does NOT update the servicefile connopt because it's already populated from step 1

The fix modifies step 2 to forcibly update servicefile when the fallback file successfully resolves the service.