kubo39's blog

ただの雑記です。

ぱっと使えそうな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をデフォルトにする?

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

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言語で型変換したかったら基本は 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

shibuya.d #2 開催しました

12/15(木)に開催しました。参加いただいた皆様、ありがとうございました。

connpass.com

当日の様子はTogetterでまとめています。ツイートの利用問題ありましたら誰でも編集可能にしているので削除お願いします。

だいたいツイートをみれば雰囲気がわかると思うので、当日話さなかった話を書きます。

shibuya.dの立ち位置

shibuya.dという勉強会は土地名を冠していますが、そういうD言語コミニュティがあるわけではなく特定の個人の思いつきで不定期にやってる集まりです。ときどき「Ustとかで配信してほしい」という要望を地方在住の方からいただくことがあります。こんな小さな勉強会で「観たい!」と思ってもらえることはとても嬉しく感じるのですが、個人が思いつきやっている活動なので限界があります。

勉強会を主催・準備するのはけっこう大変な作業です。会場の予定をおさえること/写真撮影許可をえること/飲食許可の確認/無線LANを使えるようにする手続き/プロジェクターのチェック/事前の社内通知/etc...さらに今回は発表も兼ねることになったのでそちらの作業・検証も行いました。こちらもそれなりに負担になります。当日の対応が一番大変です。開始時間までにプロジェクタやスクリーンの準備を終わらせなければいけませんし、受付・遅刻対応(twitter監視)・機材のトラブルや忘れ物にも気を配っています。けっこう神経を使う作業です。

このへんはまあだれかに言われて勉強会やってるわけじゃなくてやりたくてやってるので別にいいんですが、配信に限らず要望・要請を受けて対応する体勢を一人でとることは難しいです。(「たかがUstくらい…」と思われるかもしれませんが、配信用のPCと機材調達・回線の確保(Guest用の低品質なネットではだめ)・配信トラブルに対応するといった作業が必要になります。shibuya.dは配信トラブル対応のリスクを負いたくないので配信をやっていないという形です。)

要望・要請を受けて即座に対応できる体勢を構築するには、複数人が連携をとって入念に準備を重ねる必要があります。そのためにはshibuya.dが個人主催からコミュニティベースへと変わっていく必要があると思っています。

P.S.

いや勉強会主催ってほんと大変なんですよ、疲れるしお金になるわけでもないし。。それでもやるのは他のD言語erに会ってみたいとか、そういう場を提供することで言語コミュニティを盛り上げたいとかそういう気持ちです。

D言語でシュッとスクリプトっぽく試す

qiita.com

これがとてもいいと思い、D言語で同じようなものを作ってみた。とりあえず3rd party製のものを意識しない版。

import std.stdio;
import std.regex;
import std.format;
import std.process;
import std.path;
import std.file;
import core.stdc.stdlib;
import std.uuid;

string makeConfig()
{
    return
`{
    "name": "temp",
    "targetName": "temp",
    "targetType": "executable"
}`;
}

string makeSourceCode(string input)
{
    return format(
`
void main()
{
    %s
}`, input);
}

void main()
{
    string input;
    foreach (line; stdin.byLine)
        input ~= line;

    // create dub root dir
    auto evalDir = buildPath(tempDir(), "evald-%s/".format(randomUUID()));
    mkdirRecurse(evalDir);

    // create dub.json
    {
        scope dubJsonFile = File(buildPath(evalDir, "dub.json"), "w");
        dubJsonFile.write(makeConfig());
    }

    // create source/app.d
    {
        scope sourceDir = buildPath(evalDir, "source");
        mkdir(sourceDir);
        scope sourceFile = File(buildPath(sourceDir, "app.d"), "w");
        sourceFile.write(makeSourceCode(input));
    }

    // chdir and execute
    chdir(evalDir);
    auto dub = execute(["dub", "run"]);
    dub.output.write;

    exit(dub.status);
}
  • 実行結果

悪くないのでは

$ rdmd evald.d 
import std.stdio;
writeln("hello");
// Ctrl-d でstdinを閉じる
Performing "debug" build using dmd for x86_64.
temp ~master: building configuration "application"...
Linking...
Running ./temp 
hello

D言語とOS開発と自作OS

この記事は 自作OS Advent Calendar 2016 の3日目です。

D言語とOS開発

D言語システムプログラミング言語であり、OSを開発することのできる言語のひとつです。D言語でのOSプロジェクトはすでにいくつかあります。

Vild/PowerNex

D言語でもっとも勢いがあるOS開発プロジェクトです。 公式のD Blogでも 記事 でとりあげられてました。

Rikarin/Trinix

最近は少し勢いが落ちているようですが、PowerNex以前からあるプロジェクトで、PowerNexもこちらのプロジェクトを参考にしていました。

自作への道

既存ですでにあるとはいえ、やはりOSを一から作ってみるというのは抗いがたい魅力があります。勉強していく中で既存プロジェクトに貢献できる箇所があるかもしれませんしね。

そういうわけで作り始めたいところですが、OS開発にかんしては右も左もわからない状態です。

Writing an OS in RustD言語に移植 してみたり、OSDev WikiD BarebonesGDCコンパイラから参照実装である DMDに移植し、さらにmultiboot化 してみたりということはしたのですが、なかなかここから先には手を出せていない状態です。

D言語ならではの注意点

ちょこっとしか触っていない中でもいくつかTipsみたいなものはみつかりました。

  • @nogc / nothrow を関数呼び出しにつける

@nogc をつけておくとGCを呼び出さないことを保証できます(実は抜け道はあるのですが...) 同様に nothrow をつけると関数内から例外を呼び出さないことが保証できます。

  • 静的配列のゼロ初期化に memset(3) 呼び出しを避けるために = void を使う (?)

D言語は静的配列のゼロ初期化に memset(3) 呼び出しを呼んでおりそれを避けるために = void で初期化を防ぐ...と記憶していたんですが、今objdumpしてみるとそういう処理がみられませんでした。そもそもkubOSのほうはUbuntu 16.10にあげた影響でGCC hardenedの影響で動かなくなっていてすぐには確認できず。。近い内に続報を書こうと思います。

おわりに

これからちょっとずつペースをあげて勉強していきたいなと思っています。なんとなくマイクロカーネルのほうがかっこいいと思ってるのでそっちのほうに舵をきりたいなーというかんじです。

なんだかまとまりのない記事になってしまってすいません。。