Skip to content

feat(bigtable): build the accelerator daemon for Windows - #20455

Merged
mutianf merged 1 commit into
googleapis:mainfrom
mutianf:bigtable-accelerator-windows
Sep 8, 2026
Merged

mutianf merged 1 commit into
googleapis:mainfrom
mutianf:bigtable-accelerator-windows

Conversation

@mutianf

@mutianf mutianf commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

The accelerator daemon does not compile for GOOS=windows on any architecture:

$ GOOS=windows GOARCH=amd64 go build ./internal/accelerator/...
internal/accelerator/server.go:142:21: undefined: syscall.Umask
internal/accelerator/server.go:144:10: undefined: syscall.Umask

Identical failure for 386 and arm64. syscall.Umask is POSIX-only, and server.go called it inline around the bind to keep the socket from being world-connectable during the window between creation and the chmod that follows.

Changes

Move the bind behind a listenUDS helper with a per-platform implementation.

  • socket_unix.go (//go:build !windows) — the existing umask + chmod logic, moved verbatim. Linux behavior is unchanged; it is the same code in a new file.
  • socket_windows.go — Windows 10 1803+ and Server 2019+ support AF_UNIX and Go's net package speaks it, so the socket path and wire behavior are unchanged there.

What has no equivalent on Windows is the access control. There is no umask, and os.Chmod only toggles the read-only attribute — it cannot express "owner may connect, nobody else," so the POSIX 0077/0600 lockdown has nothing to port to. The socket instead inherits the ACL of its containing directory, which makes socket security a property of where the caller puts it. The per-daemon directory the SDK creates under the user-scoped %TEMP% is ACL'd to the user by default and satisfies this. The Windows implementation documents that requirement rather than applying a mode that would look like a defense without being one.

Gate the parent-PID watchdog behind parentPidWatchdogSupported.

This compiled on Windows but could never fire. Windows does not reparent orphans, so a daemon whose parent exits keeps reporting the dead parent's PID forever — and because Windows recycles PIDs, that stale value may later belong to an unrelated process. Polling it is not free either: os.Getppid on Windows enumerates every process on the machine through a Toolhelp snapshot, twice a second, for a signal that never arrives.

Parent death stays covered by monitorStdin, which sees EOF as soon as the parent's pipe handle closes. That is the same fallback the POSIX build already relies on when ppid is ambiguous (a ppid of 1 — orphan vs. legitimate child of pid 1).

Also corrected the identity.json mode comment, since 0600 is a no-op on Windows. The document carries only a principal email and scope list, no secret, so inheriting the directory ACL alongside the socket is acceptable.

Testing

  • windows/amd64, windows/386, windows/arm64 all build and go vet clean, including test files.
  • file confirms the output: PE32 (i386), PE32+ (x86-64), PE32+ (Aarch64).
  • Existing ./internal/accelerator/... tests pass on Linux; gofmt clean.

Scope

This makes the Go source cross-compile. Producing and shipping the Windows artifacts is a packaging change in the SDK that bundles the binary, and the spawn path there still needs to name the .exe.

There is also no CI guard against this regressing — nothing in .github/workflows/ cross-compiles today. A GOOS=windows go build step over amd64 + 386 would catch it, but that is shared repo-wide infra and felt out of scope here. Happy to add it if reviewers want it in this PR.

The daemon did not compile for GOOS=windows on any architecture:
syscall.Umask is POSIX-only, and server.go called it inline around the
bind to keep the socket from being world-connectable between creation
and the chmod that follows.

Move the bind behind a listenUDS helper with a per-platform
implementation. The POSIX version is the existing umask + chmod logic,
moved verbatim. Windows 10 1803+ and Server 2019+ support AF_UNIX and Go
speaks it, so the socket path and wire behavior are unchanged there --
what has no equivalent is the access control. Windows has no umask, and
os.Chmod only toggles the read-only attribute, so it cannot express
"owner may connect, nobody else." The socket instead inherits the ACL of
its directory, which makes socket security a property of where the
caller puts it: the per-daemon directory under the user-scoped %TEMP% is
ACL'd to the user and satisfies this. The Windows implementation
documents that requirement rather than applying a mode that would look
like a defense without being one.

Also gate the parent-PID watchdog. It compiled on Windows but could
never fire: Windows does not reparent orphans, so a daemon whose parent
exits keeps reporting the dead parent's PID forever, and because PIDs
are recycled that stale value may later belong to an unrelated process.
Polling it is not free either -- os.Getppid on Windows enumerates every
process on the machine through a Toolhelp snapshot, twice a second, for
a signal that never arrives. Parent death stays covered by monitorStdin,
which sees EOF when the parent's pipe handle closes; that is the same
fallback the POSIX build already uses when ppid is ambiguous.

Verified: windows/amd64, windows/386 and windows/arm64 build and vet
clean (including test files), and produce PE32/PE32+ binaries for i386,
x86-64 and Aarch64. Linux behavior is unchanged -- the POSIX path is the
same code in a new file.

Note that this only makes the Go source cross-compile. Producing and
shipping the Windows artifacts is a packaging change in the SDK that
bundles the binary, and the spawn path there still needs to name the
.exe.

Change-Id: I4b51f24fb55214dea1a11834c242cf6b341f5422
@mutianf
mutianf requested review from a team as code owners September 2, 2026 02:15
@product-auto-label product-auto-label Bot added the api: bigtable Issues related to the Bigtable API. label Sep 2, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Unix domain socket binding and parent PID watchdog logic to support Windows. It extracts platform-specific socket creation and restriction logic into listenUDS across separate socket_unix.go and socket_windows.go files. It also introduces a parentPidWatchdogSupported constant to skip the parent PID watchdog on Windows, where process reparenting is not supported and polling is expensive. There are no review comments, and I have no additional feedback to provide.

@mutianf
mutianf merged commit df55af5 into googleapis:main Sep 8, 2026
19 checks passed
@mutianf
mutianf deleted the bigtable-accelerator-windows branch September 8, 2026 18:32
dbolduc pushed a commit that referenced this pull request Sep 10, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.57.0](bigtable/v1.56.0...bigtable/v1.57.0)
(2026-09-10)


### Features

* **bigtable:** Build the accelerator daemon for Windows
([#20455](#20455))
([df55af5](df55af5))


### Bug Fixes

* **bigtable/bttest:** Honor timestamp_origin on SetCell
([#20469](#20469))
([528aaf8](528aaf8)),
refs
[#20468](#20468)
* **bigtable:** Keep single-key ReadRows on the streaming classic path
([#20506](#20506))
([2bfdb5d](2bfdb5d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
mutianf added a commit to googleapis/google-cloud-python that referenced this pull request Oct 26, 2026
…8778)

The Go daemon gained Windows UDS support in
googleapis/google-cloud-go#20455, so this lifts the `sys.platform ==
"win32"` block and fixes the POSIX assumptions behind it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: bigtable Issues related to the Bigtable API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants