Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19242] ファイルの概要

このコミットは、Go言語のsyscallパッケージにおいて、DragonFly BSDオペレーティングシステム上でのソケット制御メッセージ(cmsg)のハンドリングに関するバグを修正するものです。具体的には、64ビットのDragonFly BSDカーネルがネットワークサブシステムに対して32ビットのアライメントを要求するという特殊な要件に対応するため、cmsgAlignOf関数におけるアライメント計算ロジックを更新しています。これにより、DragonFly BSD環境でのソケット通信の安定性と正確性が向上します。

コミット

commit d844d6982ebd3ea2a1a146d753581018f977c6ec
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sun Apr 27 22:28:41 2014 +0900

    syscall: fix handling socket control messages on dragonfly
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/91860043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d844d6982ebd3ea2a1a146d753581018f977c6ec

元コミット内容

syscall: fix handling socket control messages on dragonfly

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/91860043

変更の背景

この変更の背景には、特定のオペレーティングシステム(OS)におけるメモリアライメントの特殊な要件があります。Go言語のsyscallパッケージは、OSのシステムコールを直接呼び出すためのインターフェースを提供しており、ネットワーク通信など低レベルな操作を行う際に利用されます。ソケットを介したデータ送受信では、補助データ(control messages、cmsg)をやり取りすることがあります。この補助データは、ファイルディスクリプタの受け渡しや、IPヘッダ情報の取得など、通常のデータとは異なるメタ情報を伝達するために使用されます。

問題は、64ビットシステムにおいて、一部のOSカーネルがネットワーク関連のデータ構造(特にsockaddr構造体やcmsgデータ)に対して、期待される64ビットアライメントではなく、32ビットアライメントを要求する場合があることです。以前のGoのsyscallパッケージでは、64ビットのDarwin(macOS)カーネルが同様の要件を持つことが知られており、これに対応するための修正が既に導入されていました。

しかし、DragonFly BSDという別のBSD系OSの64ビットカーネルも、同様にネットワークサブシステムに対して32ビットアライメントを要求するという特殊な振る舞いをすることが判明しました。Goのランタイムがこの要件を考慮せずにcmsgデータを処理しようとすると、メモリアライメントの不一致が発生し、データ破損やクラッシュといった予期せぬ動作を引き起こす可能性がありました。このコミットは、DragonFly BSD環境でのソケット制御メッセージの正しいハンドリングを保証するために、既存のDarwin向けのアライメント修正をDragonFly BSDにも拡張することを目的としています。

前提知識の解説

1. ソケット制御メッセージ (Control Messages, cmsg)

ソケット制御メッセージは、通常のデータストリームとは別に、ソケットを介して補助的な情報を送受信するためのメカニズムです。sendmsgrecvmsgといったシステムコールで使用され、msghdr構造体内のmsg_controlおよびmsg_controllenフィールドを通じてアクセスされます。 一般的な用途としては以下のようなものがあります。

  • ファイルディスクリプタの受け渡し (SCM_RIGHTS): プロセス間でファイルディスクリプタを渡すことができます。
  • IPヘッダ情報の取得 (IP_PKTINFO): 受信したIPパケットの送信元アドレスやインターフェースインデックスなどの情報を取得します。
  • ユーザー認証情報 (SCM_CREDENTIALS): 送信元のユーザーID、グループID、プロセスIDなどの情報を取得します。

cmsgデータは、cmsghdr構造体に続いて実際のデータが格納される形式を取ります。この構造体は、メッセージのタイプ、レベル、そしてデータの長さを定義します。

2. sockaddr構造体とメモリアライメント

sockaddrは、ソケットアドレスを表現するための汎用的な構造体です。具体的なアドレス形式(例: IPv4, IPv6, Unixドメイン)に応じて、sockaddr_in, sockaddr_in6, sockaddr_unなどの派生構造体が使用されます。これらの構造体は、ネットワークアドレスやポート番号などの情報を含みます。

メモリアライメントとは、データがメモリ上で特定のバイト境界に配置されることを指します。CPUは、特定のデータ型(例: 32ビット整数、64ビットポインタ)を効率的に読み書きするために、そのデータ型のサイズと同じか、それ以上の境界にデータが配置されていることを期待します。例えば、4バイトの整数は4バイト境界(アドレスが4の倍数)に、8バイトのポインタは8バイト境界に配置されるのが一般的です。

アライメントが正しくない場合(アライメントされていないアクセス)、CPUはデータを読み書きするために複数のメモリアクセスを行う必要があり、パフォーマンスが低下したり、最悪の場合、アライメント違反例外(segmentation faultなど)が発生してプログラムがクラッシュしたりすることがあります。

3. cmsgAlignOf関数の役割

cmsgAlignOf関数は、ソケット制御メッセージのデータ部分(sockaddrなどの構造体)がメモリ上で適切にアライメントされるように、その長さを調整(パディング)するために使用されます。OSカーネルが特定のデータ構造に対して特殊なアライメント要件を持つ場合、この関数はその要件を満たすように長さを「切り上げ」ます。

例えば、64ビットシステムでポインタサイズが8バイトであっても、カーネルが32ビットアライメント(4バイト境界)を要求する場合、cmsgAlignOfはデータの長さを4バイトの倍数に調整します。

4. sizeofPtr

sizeofPtrは、Goのランタイムが認識するポインタのサイズ(バイト単位)を表す定数です。32ビットシステムでは通常4、64ビットシステムでは通常8になります。これは、Goプログラムが実行されているアーキテクチャのポインタサイズを反映します。

5. DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークして開発されたオープンソースのUnix系オペレーティングシステムです。高性能とスケーラビリティを重視しており、特にSMP(Symmetric Multiprocessing)システムでの効率的な動作を目指しています。独自のファイルシステムであるHAMMERや、軽量カーネルスレッド(LWKT)などの特徴的な技術を持っています。

一部のBSD系OS(特に古いカーネルや特定のサブシステム)では、64ビット環境であっても、互換性や設計上の理由から、ネットワーク関連のデータ構造に対して32ビットアライメントを要求する場合があります。これは、カーネル内部のデータ構造が32ビットワードで設計されているため、64ビットのポインタやデータが32ビット境界に配置されることを前提としているためです。

6. Goのsyscallパッケージ

Go言語のsyscallパッケージは、低レベルなOSプリミティブへのアクセスを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信など、OSが提供するシステムコールを直接呼び出す機能が含まれます。Goの標準ライブラリの多くの部分(例: os, netパッケージ)は、内部的にこのsyscallパッケージを利用してOSと対話しています。異なるOS間で移植性を保ちつつ、OS固有の機能にアクセスするために重要なパッケージです。

技術的詳細

このコミットの技術的な核心は、Goのsyscallパッケージがソケット制御メッセージを処理する際に、DragonFly BSDの64ビットカーネルが持つ特殊なメモリアライメント要件を認識し、それに対応することです。

既存のコードでは、cmsgAlignOf関数がsockaddr構造体の長さを適切にアライメントするために使用されていました。この関数は、デフォルトではポインタサイズ(sizeofPtr)に基づいてアライメントを行いますが、64ビットのDarwinカーネルがネットワークサブシステムに対して32ビットアライメント(4バイト境界)を要求するという既知の問題に対応するため、darwin64Bitというフラグが導入されていました。darwin64Bitが真の場合、salign(アライメント境界)はsizeofPtr(8)ではなく4に設定され、32ビットアライメントが強制されます。

このコミットでは、同様の要件がDragonFly BSDの64ビットカーネルにも存在することが確認されたため、cmsgAlignOf関数内の条件式にdragonfly64Bitという新しいフラグを追加しています。

具体的には、以下の変更が行われました。

  1. dragonfly64Bit定数の追加: src/pkg/syscall/syscall_unix.goファイルに、dragonfly64Bitという新しいブール定数が追加されました。この定数は、GoがDragonFly BSD上で動作しており、かつポインタサイズが8バイト(すなわち64ビットシステム)である場合にtrueとなります。

    dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
    

    ここで、runtime.GOOSはGoプログラムが実行されているOSの名前(例: "darwin", "linux", "dragonfly")を返すGoの組み込み定数です。

  2. cmsgAlignOf関数の条件式の更新: src/pkg/syscall/sockcmsg_unix.goファイル内のcmsgAlignOf関数において、アライメント境界を決定する条件式が更新されました。 変更前:

    if darwin64Bit {
        salign = 4
    }
    

    変更後:

    if darwin64Bit || dragonfly64Bit {
        salign = 4
    }
    

    これにより、64ビットのDarwinまたはDragonFly BSDのいずれかの環境で実行されている場合、salignは4に設定され、ソケット制御メッセージのデータが32ビット境界にアライメントされるようになります。

この修正により、Goのsyscallパッケージは、DragonFly BSDの64ビット環境においても、ソケット制御メッセージの送受信時に正しいメモリアライメントを保証できるようになり、関連するシステムコールが安定して動作するようになります。これは、Goのクロスプラットフォーム互換性を高める上で重要な改善です。

コアとなるコードの変更箇所

diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go
index 2cdc28ee35..045a012c05 100644
--- a/src/pkg/syscall/sockcmsg_unix.go
+++ b/src/pkg/syscall/sockcmsg_unix.go
@@ -13,9 +13,9 @@ import "unsafe"
 // Round the length of a raw sockaddr up to align it properly.
 func cmsgAlignOf(salen int) int {
 	salign := sizeofPtr
-	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
-	// aligned access to BSD subsystem.
-	if darwin64Bit {
+	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
+	// still require 32-bit aligned access to network subsystem.
+	if darwin64Bit || dragonfly64Bit {
 		salign = 4
 	}
 	return (salen + salign - 1) & ^(salign - 1)
diff --git a/src/pkg/syscall/syscall_unix.go b/src/pkg/syscall/syscall_unix.go
index de5ff95cf1..b28891568d 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/pkg/syscall/syscall_unix.go
@@ -19,8 +19,9 @@ var (
 )
 
 const (
-	darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
-	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
+	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
+	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
 )
 
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)\n

コアとなるコードの解説

src/pkg/syscall/syscall_unix.go の変更

 const (
-	darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
-	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
+	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
+	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
 )

この部分では、Goのビルド時に特定のOSとアーキテクチャの組み合わせを識別するための定数が定義されています。

  • - darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8: 変更前は、Darwin(macOS)上で64ビット環境(ポインタサイズが8バイト)であるかを判定する定数でした。
  • + dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8: 新たに追加された行です。これは、GoがDragonFly BSD上で動作しており、かつ64ビット環境(ポインタサイズが8バイト)である場合にtrueとなる定数dragonfly64Bitを定義しています。これにより、DragonFly BSDの64ビット環境をGoのコード内で識別できるようになります。
  • netbsd32BitはNetBSDの32ビット環境を識別するための既存の定数で、このコミットでは変更されていません。

src/pkg/syscall/sockcmsg_unix.go の変更

 // Round the length of a raw sockaddr up to align it properly.
 func cmsgAlignOf(salen int) int {
 	salign := sizeofPtr
-	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
-	// aligned access to BSD subsystem.
-	if darwin64Bit {
+	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
+	// still require 32-bit aligned access to network subsystem.
+	if darwin64Bit || dragonfly64Bit {
 		salign = 4
 	}
 	return (salen + salign - 1) & ^(salign - 1)

このcmsgAlignOf関数は、ソケット制御メッセージのデータ部分の長さを、特定のOSが要求するアライメント境界に合わせて切り上げる役割を担っています。

  • salign := sizeofPtr: デフォルトのアライメント境界をポインタサイズ(64ビットシステムでは8バイト)に設定します。
  • - if darwin64Bit { salign = 4 }: 変更前は、64ビットのDarwin環境でのみ、アライメント境界を32ビット(4バイト)に強制していました。これは、Darwinカーネルがネットワークサブシステムに対して32ビットアライメントを要求するためです。
  • + if darwin64Bit || dragonfly64Bit { salign = 4 }: 変更後では、条件式に|| dragonfly64Bitが追加されました。これにより、64ビットのDarwin環境または64ビットのDragonFly BSD環境のいずれかで実行されている場合、salignが4に設定されます。これは、DragonFly BSDの64ビットカーネルも同様にネットワークサブシステムに対して32ビットアライメントを要求するという発見に基づいています。
  • return (salen + salign - 1) & ^(salign - 1): この行は、salen(元の長さ)をsalignの倍数に切り上げるためのビット演算です。例えば、salignが4の場合、salenが10であれば、(10 + 4 - 1) & ^(4 - 1) = 13 & ^3 = 13 & ~3 = 13 & 0xFFFFFFFC = 12 となり、4の倍数に切り上げられます。

これらの変更により、Goのsyscallパッケージは、DragonFly BSDの64ビット環境においても、ソケット制御メッセージのデータがカーネルの期待する32ビットアライメントで正しく配置されることを保証し、アライメント違反による潜在的な問題を回避します。

関連リンク

参考にした情報源リンク

  • Go言語のsyscallパッケージに関する公式ドキュメントやソースコード
  • BSD系OS(特にDragonFly BSD)のメモリアライメントに関する情報
  • ソケットプログラミングにおける制御メッセージ(cmsg)に関する一般的な情報
  • runtime.GOOSに関するGoのドキュメント
  • sizeofPtrに関するGoのドキュメント
  • https://golang.org/cl/91860043 (Goのコードレビューシステム)# [インデックス 19242] ファイルの概要

このコミットは、Go言語のsyscallパッケージにおいて、DragonFly BSDオペレーティングシステム上でのソケット制御メッセージ(cmsg)のハンドリングに関するバグを修正するものです。具体的には、64ビットのDragonFly BSDカーネルがネットワークサブシステムに対して32ビットのアライメントを要求するという特殊な要件に対応するため、cmsgAlignOf関数におけるアライメント計算ロジックを更新しています。これにより、DragonFly BSD環境でのソケット通信の安定性と正確性が向上します。

コミット

commit d844d6982ebd3ea2a1a146d753581018f977c6ec
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sun Apr 27 22:28:41 2014 +0900

    syscall: fix handling socket control messages on dragonfly
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/91860043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d844d6982ebd3ea2a1a146d753581018f977c6ec

元コミット内容

syscall: fix handling socket control messages on dragonfly

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/91860043

変更の背景

この変更の背景には、特定のオペレーティングシステム(OS)におけるメモリアライメントの特殊な要件があります。Go言語のsyscallパッケージは、OSのシステムコールを直接呼び出すためのインターフェースを提供しており、ネットワーク通信など低レベルな操作を行う際に利用されます。ソケットを介したデータ送受信では、補助データ(control messages、cmsg)をやり取りすることがあります。この補助データは、ファイルディスクリプタの受け渡しや、IPヘッダ情報の取得など、通常のデータとは異なるメタ情報を伝達するために使用されます。

問題は、64ビットシステムにおいて、一部のOSカーネルがネットワーク関連のデータ構造(特にsockaddr構造体やcmsgデータ)に対して、期待される64ビットアライメントではなく、32ビットアライメントを要求する場合があることです。以前のGoのsyscallパッケージでは、64ビットのDarwin(macOS)カーネルが同様の要件を持つことが知られており、これに対応するための修正が既に導入されていました。

しかし、DragonFly BSDという別のBSD系OSの64ビットカーネルも、同様にネットワークサブシステムに対して32ビットアライメントを要求するという特殊な振る舞いをすることが判明しました。Goのランタイムがこの要件を考慮せずにcmsgデータを処理しようとすると、メモリアライメントの不一致が発生し、データ破損やクラッシュといった予期せぬ動作を引き起こす可能性がありました。このコミットは、DragonFly BSD環境でのソケット制御メッセージの正しいハンドリングを保証するために、既存のDarwin向けのアライメント修正をDragonFly BSDにも拡張することを目的としています。

前提知識の解説

1. ソケット制御メッセージ (Control Messages, cmsg)

ソケット制御メッセージは、通常のデータストリームとは別に、ソケットを介して補助的な情報を送受信するためのメカニズムです。sendmsgrecvmsgといったシステムコールで使用され、msghdr構造体内のmsg_controlおよびmsg_controllenフィールドを通じてアクセスされます。 一般的な用途としては以下のようなものがあります。

  • ファイルディスクリプタの受け渡し (SCM_RIGHTS): プロセス間でファイルディスクリプタを渡すことができます。
  • IPヘッダ情報の取得 (IP_PKTINFO): 受信したIPパケットの送信元アドレスやインターフェースインデックスなどの情報を取得します。
  • ユーザー認証情報 (SCM_CREDENTIALS): 送信元のユーザーID、グループID、プロセスIDなどの情報を取得します。

cmsgデータは、cmsghdr構造体に続いて実際のデータが格納される形式を取ります。この構造体は、メッセージのタイプ、レベル、そしてデータの長さを定義します。

2. sockaddr構造体とメモリアライメント

sockaddrは、ソケットアドレスを表現するための汎用的な構造体です。具体的なアドレス形式(例: IPv4, IPv6, Unixドメイン)に応じて、sockaddr_in, sockaddr_in6, sockaddr_unなどの派生構造体が使用されます。これらの構造体は、ネットワークアドレスやポート番号などの情報を含みます。

メモリアライメントとは、データがメモリ上で特定のバイト境界に配置されることを指します。CPUは、特定のデータ型(例: 32ビット整数、64ビットポインタ)を効率的に読み書きするために、そのデータ型のサイズと同じか、それ以上の境界にデータが配置されていることを期待します。例えば、4バイトの整数は4バイト境界(アドレスが4の倍数)に、8バイトのポインタは8バイト境界に配置されるのが一般的です。

アライメントが正しくない場合(アライメントされていないアクセス)、CPUはデータを読み書きするために複数のメモリアクセスを行う必要があり、パフォーマンスが低下したり、最悪の場合、アライメント違反例外(segmentation faultなど)が発生してプログラムがクラッシュしたりすることがあります。

3. cmsgAlignOf関数の役割

cmsgAlignOf関数は、ソケット制御メッセージのデータ部分(sockaddrなどの構造体)がメモリ上で適切にアライメントされるように、その長さを調整(パディング)するために使用されます。OSカーネルが特定のデータ構造に対して特殊なアライメント要件を持つ場合、この関数はその要件を満たすように長さを「切り上げ」ます。

例えば、64ビットシステムでポインタサイズが8バイトであっても、カーネルが32ビットアライメント(4バイト境界)を要求する場合、cmsgAlignOfはデータの長さを4バイトの倍数に調整します。

4. sizeofPtr

sizeofPtrは、Goのランタイムが認識するポインタのサイズ(バイト単位)を表す定数です。32ビットシステムでは通常4、64ビットシステムでは通常8になります。これは、Goプログラムが実行されているアーキテクチャのポインタサイズを反映します。

5. DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークして開発されたオープンソースのUnix系オペレーティングシステムです。高性能とスケーラビリティを重視しており、特にSMP(Symmetric Multiprocessing)システムでの効率的な動作を目指しています。独自のファイルシステムであるHAMMERや、軽量カーネルスレッド(LWKT)などの特徴的な技術を持っています。

一部のBSD系OS(特に古いカーネルや特定のサブシステム)では、64ビット環境であっても、互換性や設計上の理由から、ネットワーク関連のデータ構造に対して32ビットアライメントを要求する場合があります。これは、カーネル内部のデータ構造が32ビットワードで設計されているため、64ビットのポインタやデータが32ビット境界に配置されることを前提としているためです。

6. Goのsyscallパッケージ

Go言語のsyscallパッケージは、低レベルなOSプリミティブへのアクセスを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信など、OSが提供するシステムコールを直接呼び出す機能が含まれます。Goの標準ライブラリの多くの部分(例: os, netパッケージ)は、内部的にこのsyscallパッケージを利用してOSと対話しています。異なるOS間で移植性を保ちつつ、OS固有の機能にアクセスするために重要なパッケージです。

技術的詳細

このコミットの技術的な核心は、Goのsyscallパッケージがソケット制御メッセージを処理する際に、DragonFly BSDの64ビットカーネルが持つ特殊なメモリアライメント要件を認識し、それに対応することです。

既存のコードでは、cmsgAlignOf関数がsockaddr構造体の長さを適切にアライメントするために使用されていました。この関数は、デフォルトではポインタサイズ(sizeofPtr)に基づいてアライメントを行いますが、64ビットのDarwinカーネルがネットワークサブシステムに対して32ビットアライメント(4バイト境界)を要求するという既知の問題に対応するため、darwin64Bitというフラグが導入されていました。darwin64Bitが真の場合、salign(アライメント境界)はsizeofPtr(8)ではなく4に設定され、32ビットアライメントが強制されます。

このコミットでは、同様の要件がDragonFly BSDの64ビットカーネルにも存在することが確認されたため、cmsgAlignOf関数内の条件式にdragonfly64Bitという新しいフラグを追加しています。

具体的には、以下の変更が行われました。

  1. dragonfly64Bit定数の追加: src/pkg/syscall/syscall_unix.goファイルに、dragonfly64Bitという新しいブール定数が追加されました。この定数は、GoがDragonFly BSD上で動作しており、かつポインタサイズが8バイト(すなわち64ビットシステム)である場合にtrueとなります。

    dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
    

    ここで、runtime.GOOSはGoプログラムが実行されているOSの名前(例: "darwin", "linux", "dragonfly")を返すGoの組み込み定数です。

  2. cmsgAlignOf関数の条件式の更新: src/pkg/syscall/sockcmsg_unix.goファイル内のcmsgAlignOf関数において、アライメント境界を決定する条件式が更新されました。 変更前:

    if darwin64Bit {
        salign = 4
    }
    

    変更後:

    if darwin64Bit || dragonfly64Bit {
        salign = 4
    }
    

    これにより、64ビットのDarwinまたはDragonFly BSDのいずれかの環境で実行されている場合、salignは4に設定され、ソケット制御メッセージのデータが32ビット境界にアライメントされるようになります。

この修正により、Goのsyscallパッケージは、DragonFly BSDの64ビット環境においても、ソケット制御メッセージの送受信時に正しいメモリアライメントを保証できるようになり、関連するシステムコールが安定して動作するようになります。これは、Goのクロスプラットフォーム互換性を高める上で重要な改善です。

コアとなるコードの変更箇所

diff --git a/src/pkg/syscall/sockcmsg_unix.go b/src/pkg/syscall/sockcmsg_unix.go
index 2cdc28ee35..045a012c05 100644
--- a/src/pkg/syscall/sockcmsg_unix.go
+++ b/src/pkg/syscall/sockcmsg_unix.go
@@ -13,9 +13,9 @@ import "unsafe"
 // Round the length of a raw sockaddr up to align it properly.
 func cmsgAlignOf(salen int) int {
 	salign := sizeofPtr
-	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
-	// aligned access to BSD subsystem.
-	if darwin64Bit {
+	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
+	// still require 32-bit aligned access to network subsystem.
+	if darwin64Bit || dragonfly64Bit {
 		salign = 4
 	}
 	return (salen + salign - 1) & ^(salign - 1)
diff --git a/src/pkg/syscall/syscall_unix.go b/src/pkg/syscall/syscall_unix.go
index de5ff95cf1..b28891568d 100644
--- a/src/pkg/syscall/syscall_unix.go
+++ b/src/pkg/syscall/syscall_unix.go
@@ -19,8 +19,9 @@ var (
 )
 
 const (
-	darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
-	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
+	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
+	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
 )
 
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)\n

コアとなるコードの解説

src/pkg/syscall/syscall_unix.go の変更

 const (
-	darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
-	netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
+	dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
+	netbsd32Bit    = runtime.GOOS == "netbsd" && sizeofPtr == 4
 )

この部分では、Goのビルド時に特定のOSとアーキテクチャの組み合わせを識別するための定数が定義されています。

  • - darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8: 変更前は、Darwin(macOS)上で64ビット環境(ポインタサイズが8バイト)であるかを判定する定数でした。
  • + dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8: 新たに追加された行です。これは、GoがDragonFly BSD上で動作しており、かつ64ビット環境(ポインタサイズが8バイト)である場合にtrueとなる定数dragonfly64Bitを定義しています。これにより、DragonFly BSDの64ビット環境をGoのコード内で識別できるようになります。
  • netbsd32BitはNetBSDの32ビット環境を識別するための既存の定数で、このコミットでは変更されていません。

src/pkg/syscall/sockcmsg_unix.go の変更

 // Round the length of a raw sockaddr up to align it properly.
 func cmsgAlignOf(salen int) int {
 	salign := sizeofPtr
-	// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
-	// aligned access to BSD subsystem.
-	if darwin64Bit {
+	// NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
+	// still require 32-bit aligned access to network subsystem.
+	if darwin64Bit || dragonfly64Bit {
 		salign = 4
 	}
 	return (salen + salign - 1) & ^(salign - 1)

このcmsgAlignOf関数は、ソケット制御メッセージのデータ部分の長さを、特定のOSが要求するアライメント境界に合わせて切り上げる役割を担っています。

  • salign := sizeofPtr: デフォルトのアライメント境界をポインタサイズ(64ビットシステムでは8バイト)に設定します。
  • - if darwin64Bit { salign = 4 }: 変更前は、64ビットのDarwin環境でのみ、アライメント境界を32ビット(4バイト)に強制していました。これは、Darwinカーネルがネットワークサブシステムに対して32ビットアライメントを要求するためです。
  • + if darwin64Bit || dragonfly64Bit { salign = 4 }: 変更後では、条件式に|| dragonfly64Bitが追加されました。これにより、64ビットのDarwin環境または64ビットのDragonFly BSD環境のいずれかで実行されている場合、salignが4に設定されます。これは、DragonFly BSDの64ビットカーネルも同様にネットワークサブシステムに対して32ビットアライメントを要求するという発見に基づいています。
  • return (salen + salign - 1) & ^(salign - 1): この行は、salen(元の長さ)をsalignの倍数に切り上げるためのビット演算です。例えば、salignが4の場合、salenが10であれば、(10 + 4 - 1) & ^(4 - 1) = 13 & ^3 = 13 & ~3 = 13 & 0xFFFFFFFC = 12 となり、4の倍数に切り上げられます。

これらの変更により、Goのsyscallパッケージは、DragonFly BSDの64ビット環境においても、ソケット制御メッセージのデータがカーネルの期待する32ビットアライメントで正しく配置されることを保証し、アライメント違反による潜在的な問題を回避します。

関連リンク

参考にした情報源リンク

  • Go言語のsyscallパッケージに関する公式ドキュメントやソースコード
  • BSD系OS(特にDragonFly BSD)のメモリアライメントに関する情報
  • ソケットプログラミングにおける制御メッセージ(cmsg)に関する一般的な情報
  • runtime.GOOSに関するGoのドキュメント
  • sizeofPtrに関するGoのドキュメント
  • https://golang.org/cl/91860043 (Goのコードレビューシステム)