読者です 読者をやめる 読者になる 読者になる

kubo39's blog

ただの雑記です。

DMD on FreeBSD

D言語 Freebsd

だいたいこの記事のとおりなんだけど、細々と補足をしておく。

まず選定したFreeBSDのboxの話。最初はfreebsd/FreeBSD-11.0-STABLEのboxを試していたのだけど、これは毎度VMが突然シャットダウンしてしまって使い物にならなかったためにfreebsd/FreeBSD-11.0-RELEASE-p1を使うことになった。ログも一応目を通したが原因はさっぱり不明。これはけっこう時間を喰ってしまった。

いったんFreeBSDを入れてしまうと案外楽に環境構築はできた。記事中のbash/gcc/curlもpkgでバイナリで手軽にインストールできた他、gitやzshemacs-nox11もあっさりバイナリインストールして既存のLinux環境とだいたい同じような環境を構築できた。まったく同じというわけにはいかずGNU toolとBSD toolにはオプションの差異があるが(lsやnmなど)、そこはmanを見ながら地道に解決していくしかない。

portsのセットアップもNetBSDOpenBSDに比べるとずっと簡単で、だいたいここの通りにやれば解決する。というかOpenBSDportsのmakeがX11に依存してるのおかしいでしょ、X11がなんか壊れたのでportsが機能しなくなってしまったんだよなあ。

D言語環境の構築は公式の提供しているバイナリインストーラを使ったのは元記事に追記しているとおりportsのlang/dmd2がやや古いバージョンであったため。ていうか最新のportsにはまだlang/dmd1が入ってる。最新版のdmd-2.073.0に比べ2017年1月27日時点でのlang/dmd2は2.071.1であった。バイナリインストーラは引数にldcgdcも受け付けられるので他のコンパイラFreeBSDで簡単に動かせるかもしれない。

ところでこの公式インストーラで入るdub、libphobos2.072.2.soに動的リンクしているため、さらにdmd-2.072.2をダウンロードしてdmd-2.073.0より先にactivateするようにして運用している。これはバグなんだろうか。

D言語環境を構築したので https://github.com/kubo39/syscall-d とか https://github.com/kubo39/tiny-d-demo といったプログラムを試しにFreeBSD上でも動くように修正してみた。このあたりはわりと簡単に動かせる状態にできた。

環境構築まわり

開発環境

どういうツール使ってるかなどまとめておくと移行のときよさそう?

最近使ってるツールだらだらあげていく。

Tool

  • emacs
  • git
  • zsh
  • tree
  • gcc
  • nasm
  • anyenv (pyenv/rbenv/denv)
  • rustup
  • rg
  • binutils (gdb/readelf/objdump/file/nm/etc..)
  • strace
  • ltrace
  • valgrind
  • perf
  • rr
  • wrk
  • firejail

OS setup (ubuntu)

sudo apt install build-essential tree curl valgrind nasm -y
env LANGUAGE=C LC_MESSAGES=C xdg-user-dirs-gtk-update

これから試してみるつもり系

  • tig
  • pv
  • powertop

FreeBSDとNetBSDとOpenBSDをVirtualBox on OSXでいろいろ触る

Freebsd NetBSD OpenBSD

ここのところ仕事そっちのけでやっています。

FreeBSD 11-STABLE

vagrant init freebsd/FreeBSD-11.0-RELEASEしてvagrant upすると作れる。

デフォルトのシェルはcshだったかな。pkg installでだいたい入るので便利。rustupも使えるしcargo installでripgrepも入る。sys-info crateがFreeBSD対応してなくてparallel crateが動かなかったりはする。dmdは現時点で最新版の2.073.0を入れてみたがlibstdc++.soが見つからないとかで動かなかった。これはgccが入っていないからである。

ただしOSXVirtualBoxFreeBSDを動かしていると突然VMが死ぬのが難点。

NetBSD 7.0

こちらもvagrantでいける。

デフォルトのシェルはbash。PKG_PATHの指定してpkg_addで入れる。デフォルトで入ってるcurlが古くてgitが入らなかったのでpkg_add -u curlしてからpkg_add gitした。rustupがなんかcurlの警告で動かず、rust 1.11がパッケージに入ってるとあったがなんかうまいこといかなかった。

vagrant# PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# export PKG_PATH
vagrant# pkg_add rust-1.11.0nb1
pkg_add: Can't process ftp://ftp.NetBSD.org:21/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All/rust-1*: File unavailable (e.g., file busy)
pkg_add: no pkg found for 'rust-1.11.0nb1', sorry.
pkg_add: 1 package addition failed
vagrant# pkg_add ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/lang/rust
pkg_add: no pkg found for 'ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/lang/rust', sorry.
pkg_add: 1 package addition failed
vagrant# ^D-bash-4.3$
-bash-4.3$ sudo -i pkg_info
Terminal type is xterm-256color.
We recommend that you create a non-root account and use su(1) for root access.
pkg_install-20150901nb1 Package management and administration tools for pkgsrc
libarchive-3.1.2nb2 Library to read/create different archive formats
pkgin-0.9.4nb1      Apt / yum like tool for managing pkgsrc binary packages
libidn-1.32         Internationalized Domain Names command line tool
bash-4.3.039        The GNU Bourne Again Shell
sudo-1.8.15nb1      Allow others to run commands as root
wget-1.17.1nb1      Retrieve files from the 'net via HTTP and FTP
curl-7.47.1nb1      Client that groks URLs
digest-20160304     Message digest wrapper utility
perl-5.24.0         Practical Extraction and Report Language
libatomic_ops-7.4.4 Multi-platform library of atomic operations by Hans Boehm
boehm-gc-7.6.0nb2   Garbage collection and memory leak detection for C and C++
w3m-0.5.3.0.20161120 Multilingualized version of a pager/text-based browser w3m
-bash-4.3$ su
Password:
vagrant# pkg_add git
pkg_add: no pkg found for 'git', sorry.
pkg_add: 1 package addition failed
vagrant# export PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# pkg_add git
pkg_add: A different version of curl-7.52.1 is already installed: curl-7.47.1nb1
pkg_add: Can't install dependency curl>=7.50.3nb1
pkg_add: Can't install dependency git-base>=2.11.0
pkg_add: 1 package addition failed
vagrant# ^D-bash-4.3$
-bash-4.3$ su
Password:
vagrant# echo $PKG_PATH

vagrant# export PKG_PATH="ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/x86_64/7.0/All"
vagrant# pkg_add zsh
zsh-5.3: adding /usr/pkg/bin/zsh to /etc/shells
zsh-5.3: registering info file /usr/pkg/info/zsh.info
vagrant# ^D-bash-4.3$ chsh -s $(which zsh)
-bash-4.3$ su
vagrant# pkg_add -u curl
vagrant# curl --version
curl 7.52.1 (x86_64--netbsd) libcurl/7.52.1 OpenSSL/1.0.1p zlib/1.2.3
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets HTTPS-proxy
vagrant# pkg_add git
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/description to /usr/pkg/share/git-core/templates/description
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/applypatch-msg.sample to /usr/pkg/share/git-core/templates/hooks/applypatch-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/commit-msg.sample to /usr/pkg/share/git-core/templates/hooks/commit-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/post-update.sample to /usr/pkg/share/git-core/templates/hooks/post-update.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-applypatch.sample to /usr/pkg/share/git-core/templates/hooks/pre-applypatch.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-commit.sample to /usr/pkg/share/git-core/templates/hooks/pre-commit.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/pre-rebase.sample to /usr/pkg/share/git-core/templates/hooks/pre-rebase.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/prepare-commit-msg.sample to /usr/pkg/share/git-core/templates/hooks/prepare-commit-msg.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/hooks/update.sample to /usr/pkg/share/git-core/templates/hooks/update.sample
git-base-2.11.0: copying /usr/pkg/share/examples/git/templates/info/exclude to /usr/pkg/share/git-core/templates/info/exclude
===========================================================================
$NetBSD: MESSAGE,v 1.3 2016/05/26 15:41:06 khorben Exp $

NOTE:   Pristine templates are located in:
        /usr/pkg/share/examples/git/templates.

To use the git-cvsimport repository conversion from CVS, install git-cvs.

To use the git-svn interface to Subversion, install git-svn.

===========================================================================

OpenBSD 6.0

こちらもvagrantでいける。

デフォルトのシェルはksh。なんかわりとあっさりpkgまわりがいってしまったので拍子抜け。オレオレdotfilesもzshでうまいこと動くし。 なんとrustもパッケージがあったが1.9というかなり古いバージョンだったので残念。

D言語はそもそもPhobosOpenBSD対応してないので

# export PKG_PATH=http://ftp.jaist.ac.jp/pub/OpenBSD/$(uname -r)/packages/$(uname -p)/
# pkg_add curl
quirks-2.241 signed on 2016-07-26T16:56:10Z
curl-7.49.0:nghttp2-1.12.0: ok
curl-7.49.0:libiconv-1.14p3: ok
curl-7.49.0:gettext-0.19.7: ok
curl-7.49.0:libidn-1.32p1: ok
curl-7.49.0: ok
# pkg_add rust
quirks-2.241 signed on 2016-07-26T16:56:10Z
rust-1.9.0:gcc-libs-4.9.3p9: ok
rust-1.9.0: ok
# rustc --version
rustc 1.9.0
# pkg_add cargo
quirks-2.241 signed on 2016-07-26T16:56:10Z
cargo-0.10.0:libssh2-1.7.0: ok
cargo-0.10.0: ok
# pkg_info
cargo-0.10.0        package manager for Rust language
curl-7.49.0         get files from FTP, Gopher, HTTP or HTTPS servers
gcc-libs-4.9.3p9    GNU compiler collection: support libs
gettext-0.19.7      GNU gettext runtime libraries and programs
libiconv-1.14p3     character set conversion library
libidn-1.32p1       internationalized string handling
libssh2-1.7.0       library implementing the SSH2 protocol
nghttp2-1.12.0      library for HTTP/2
quirks-2.241        exceptions to pkg_add rules
rsync-3.1.2p0       mirroring/synchronization over low bandwidth links
rust-1.9.0          compiler for Rust Language
sudo-1.8.17.1       execute a command as another user
# pkg_add emacs
quirks-2.241 signed on 2016-07-26T16:56:10Z
Ambiguous: choose package for emacs
a       0: <None>
        1: emacs-21.4p36
        2: emacs-21.4p36-no_x11
        3: emacs-24.5p5-gtk2
        4: emacs-24.5p5-gtk3
        5: emacs-24.5p5-no_x11
Your choice: 5
emacs-24.5p5-no_x11:libffi-3.2.1p2: ok
emacs-24.5p5-no_x11:libtasn1-4.8: ok
emacs-24.5p5-no_x11:p11-kit-0.23.2p0: ok
emacs-24.5p5-no_x11:gmp-5.0.2p3: ok
emacs-24.5p5-no_x11:libnettle-3.2: ok
emacs-24.5p5-no_x11:gnutls-3.4.14: ok
emacs-24.5p5-no_x11:xz-5.2.2p0: ok
emacs-24.5p5-no_x11:libxml-2.9.3: ok
emacs-24.5p5-no_x11: ok
Look in /usr/local/share/doc/pkg-readmes for extra documentation.
# pkg_add zsh
quirks-2.241 signed on 2016-07-26T16:56:10Z
zsh-5.2p3:pcre-8.38p0: ok
zsh-5.2p3: ok
# pkg_add git
quirks-2.241 signed on 2016-07-26T16:56:10Z
git-2.9.0:p5-Error-0.17024: ok
git-2.9.0:cvsps-2.1p0: ok
git-2.9.0: ok
The following new rcscripts were installed: /etc/rc.d/gitdaemon
See rcctl(8) for details.
Look in /usr/local/share/doc/pkg-readmes for extra documentation.

~~ dotfiles入れて.zshenvとか適用 ~~

$ sudo -i pkg_info                                                                                                            [openbsd60:rust]
cargo-0.10.0        package manager for Rust language
curl-7.49.0         get files from FTP, Gopher, HTTP or HTTPS servers
cvsps-2.1p0         generate patchsets from CVS repositories
emacs-24.5p5-no_x11 GNU editor: extensible, customizable, self-documenting
gcc-libs-4.9.3p9    GNU compiler collection: support libs
gettext-0.19.7      GNU gettext runtime libraries and programs
git-2.9.0           GIT - Tree History Storage Tool
gmp-5.0.2p3         library for arbitrary precision arithmetic
gnutls-3.4.14       GNU Transport Layer Security library
libffi-3.2.1p2      Foreign Function Interface
libiconv-1.14p3     character set conversion library
libidn-1.32p1       internationalized string handling
libnettle-3.2       cryptographic library
libssh2-1.7.0       library implementing the SSH2 protocol
libtasn1-4.8        Abstract Syntax Notation One structure parser library
libxml-2.9.3        XML parsing library
nghttp2-1.12.0      library for HTTP/2
p11-kit-0.23.2p0    library for loading and enumurating of PKCS#11 modules
p5-Error-0.17024    error/exception handling in an OO-ish way
pcre-8.38p0         perl-compatible regular expression library
quirks-2.241        exceptions to pkg_add rules
rsync-3.1.2p0       mirroring/synchronization over low bandwidth links
rust-1.9.0          compiler for Rust Language
sudo-1.8.17.1       execute a command as another user
xz-5.2.2p0          LZMA compression and decompression tools
zsh-5.2p3           Z shell, Bourne shell-compatible

ぱっと使えそうなRust製のツール

Rust

cargo installで入れられそうなやつを雑にまとめてみた。

  • ripgrep(rg) - はやいgrep、あるいはag。

  • xsv - CSVツールキット。

  • alacritty - 速いらしいターミナルエミュレータ

  • parallel - GNU parallelのRust版。

  • coreutils - GNU coreutilsのポート。使えないオプションや未実装のものも結構ある。

  • oxipng - pngファイルのサイズ圧縮。

  • rpc-perf - twitter製のrpcのベンチマークツール。memcachedの設定いじったときとか。

  • watchexec - ファイル変更にhookしてコマンド実行するユーティリティ。

  • flow - logのリアルタイム解析。

  • exa - lsのRust実装。デフォルトでいい感じになっているがコマンド体系が違うので慣れずに使わなくなってしまった。git対応とかしてる。

  • mdBook - markdownから本っぽいウェブサイト(html) を生成する。前使ったときはなんかうまくいかなった記憶がある。

  • panopticon - disassembler。何回か試そうとしたがqmlrsがビルドできなかった(ぱっと使えそうとは)

  • svgbobrus - ascii artからSVGファイル生成するツール。

  • skim - fzfとかpeco的なやつ。

  • git-journal - commit logからChangeLogを生成するためのツール。

  • git-series - Track changes to a patch series over time... ってよくわからんので後で調べる。LinuxConだかで発表があったのでなんかすごい(すごい)

  • arch-audit - FreeBSDのpkg-auditのArch Linux版。CVEに登録された脆弱性のあるパッケージを使っているかチェックできる。Arch Linuxでしか使えないので注意。

まだまだありそうなので、みつけたら随時追加します。

D言語でFD_CLOEXECをデフォルトにする?

D言語

表題のとおりの提案をしてみたいと思った。(思っただけ)

FD継承はUNIXの伝統だが、意図しない継承によって様々なセキュリティ上の問題を引き起こしてきた。(APIデザインケーススタディとかPEP446あたり参照)

そのため最近の言語 (Perl/Go/Ruby/Python/Rustとか) では標準入出力以外はデフォルトでCLOEXECを指定し、fork-execされるタイミングでのFD継承を行わないようなデザインにしている。

Related Work

And Go/Perl also set CLOEXEC by default.

実装案

  1. AtomicにCLOEXECを設定できる場合はそうする。(ex: open(2)のO_CLOEXECフラグ)
  2. そうでない場合はfcntl(2)でO_CLOEXECを指定する。

druntimeに追加する必要があるもの

  • pipe2(2)
  • accept4(4)
  • dup3(2)
  • mkostemp(3)
  • mkostemps(3)

Phobos側で対応が必要なもの

  • druntimeに追加したものに置き換えられるものは使う
  • フラグで追加できるものはフラグ追加で対応(Linux
    • open(2)
    • socket(2)
    • socketpair(2)
    • fopen(3)
    • freopen(3)
  • だめならfcntl(2)でO_CLOEXECをセット

課題

  • Linuxや*BSDのバージョンによってサポートされているタイミングがまちまち
    • Rustのように動的にフォールバックする仕組み?

そもそもdlang forumあたりで提案されてるんじゃないかって気がしてきた、見つからなかったけど。

2016年にやったこと

便乗してまとめておきます。

ギョーム

死んだ目でひたすらgrep業してたことしか覚えていません。はやく転職したいです。

shibuya.d

2回やりました。

shibuya.d #1 - connpass

shibuya.d #2 - connpass

来年は未定です。筑波でやるらしいので引退?

OSS?

なんかわりと雑にPR出したりしてた。

elfhook.d って今年だったのか。。これはギョームで使えるかなと思ったんですが、まあ結局もろもろあってやりませんでした。

あとは小さいのいくつか投げたり。ただどれもソース読んで投げたやつで、実際になにかのプロジェクトで使ったわけではないのでよくなかったなあ、と。

Set EPOLL_CLOEXEC flag when epoll instance created. by kubo39 · Pull Request #71 · etcimon/libasync · GitHub

  • Rust

いくつかPR出してmergeされました。まあ大したやつじゃないです。

Add epoll_create1. by kubo39 · Pull Request #328 · rust-lang/libc · GitHub

epoll: Add EPOLLEXCLUSIVE flag. by kubo39 · Pull Request #330 · nix-rust/nix · GitHub

発表とか

いろいろアウトプットする機会はあったと思います。shibuya.dは1回目はホストで手一杯だったけど2回目は発表したし、Rust LT会でも発表しました。ただTipsとかじゃなくてもう少し骨子のしっかりしたやつをやっていきたいですね。

来年

  • 経験を通して深い知識を取得してアウトプットできるようにする
  • ショボいやつじゃなくてちゃんといけてる感じのPR出せるように努力する
  • 自分の知識では難しい、恥かくだけ。と思ってももっと積極的に手を広げる
  • マルチスレッド・プロセッサ技術の勉強したい
  • アルゴリズム・データ構造系の勉強したい
  • 自作OSを進める(たすけて)

D言語のcast

D言語

D言語で型変換したかったら基本は std.conv.to 使うのが安全である。

import std.conv;

void main()
{
    int a = 1;
    long b = a.to!long;
    assert(b == 1);
}

std.conv.toは安全であるが、安全であるということは制約が強いということでもある。例えば以下のコードはOverflowを検知し例外を投げる。

import std.conv : to;

void main()
{
    auto a = -11; // int
    ulong b = a.to!ulong;
}
$ rdmd -fPIC to.d 
std.conv.ConvOverflowException@/home/kubo39/dlang/dmd-2.072.1/linux/bin64/../../src/phobos/std/conv.d(445): Conversion negative overflow
----------------
??:? pure @safe bool std.exception.enforce!(bool).enforce(bool, lazy object.Throwable) [0xde158fb2]
??:? pure @safe ulong std.conv.toImpl!(ulong, int).toImpl(int) [0xde158f34]
??:? pure @safe ulong std.conv.to!(ulong).to!(int).to(int) [0xde158f00]
??:? _Dmain [0xde158ef0]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x6dda5387]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x6dda52b3]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x6dda532c]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x6dda52b3]
??:? _d_run_main [0x6dda5217]
??:? main [0xde159047]
??:? __libc_start_main [0x6d5413f0]

こういうことがやりたいときもたまにあって、そういうときは cast を使う。

import std.stdio;

void main()
{
    auto a = -1;
    uint b = cast(uint) a;
    b.writeln;
}

castは危険な操作を許容する。例えば以下のようなコードはコンパイルが通り、未定義動作となる。

void main()
{
    ubyte[4] arr = [0, 1, 0, 0];
    auto ptr = cast(uint*) arr.ptr;
    assert(*ptr == 256);
    auto ptr2 = cast(ulong*) ptr;
    import std.stdio;
    (*ptr2).writeln;  // 未定義
}
(dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 
139972984176896
(dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 
140411070841088
(dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 
140045998620928
(dmd-2.072.1)( ՞ਊ ՞) :~/dev/misc $ rdmd -fPIC cast.d 
256