Fcitxに手こずったArch再インストール

少し早めの大掃除とPCにArch Linuxクリーンインストールしました。 /rootと/varを大きめに取り、swapパーティションを設定しgnomeを入れたまでは良かったのですがfcitxが変な挙動をするようになっていました。

fcitx-gtk3を使うと、アドオンのFcitx XIM Frontendが有効化されていると左下に変換パネルが表示されてしまい、無効化すると変換が確定するまでテキスト入力エリアに表示されない、変換途中で文字を入力し直すなどすると意図してない文字が入力されるなどの症状ができるようになりました。

適当に何度かアドオンの組み合わせを変更してみましたが一向に改善する気配がなかったのでfcitx-gtk3をアンインストールしfcitx-gtk2に切り替えると問題なく動作するようになりました。

なぜgtk3だとダメなんだ...

D言語のオフラインドキュメントのビルド

人権がない(十分に高速なインタネット環境が無い)場合でもD言語のドキュメントが読めるようにビルドしておく方法です。

git clone https://github.com/dlang/dlang.org
cd dlang.org
# LATEST=の部分は適宜バージョンに合わせて読み替えてください。
make -f posix.mak LATEST=2.072.0 docs

実行するとカレントディレクトリ内のwebディレクトリにビルドされたdlang.orgが出来ています。あとはその中身だけ適当なディレクトリに移し替えてcloneしてきたdlang.orgのローカルリポジトリを削除すれば良いだけです。 マルチコアCPUの場合はmakeする際に-jオプションを付けて並列化するとビルドが早くなり嬉しいかもしれません。

修正

make -f posix.mak LATEST=2.072.0 html

ではphobosのドキュメントがビルドされないようです。

D言語でclass同士のopEqualsをオーバーロードする

D言語のclass同士の等価比較演算子オーバーロードは少々特殊です。

structだと

struct S {
    int x;
    bool opEquals(S s) {
        return x == s.x;
    }
}

と書けますがclassの場合だと

class C {
    int x;
    override bool opEquals(Object o) {
        auto c = cast(C)o;
        if (c is null) return false;
        return x == c.x;
    }
}

のように書きます。 D言語ではclassにopEqualsが実装されてる際にはobject.opEqualsの定義に従って比較がされます。 object.opEqualsは以下のように定義されています(実際のソースコードは多少の違いがありますが)

bool opEquals(Object a, Object b)
{
    if (a is b) return true;
    if (a is null || b is null) return false;
    if (typeid(a) == typeid(b)) return a.opEquals(b);
    return a.opEquals(b) && b.opEquals(a);
}

この定義を見れば分かるようにopEqualsには比較対象がなんであってもObjectが渡されるので引数はObjectでなくてはいけません。また、全てのクラスの基底クラスであるObjectには

class Object{
//省略
    bool opEquals(Object o) {
        return this is o;
    }
//省略
}

とopEqualsが実装されているのでopEqualsにはoverride修飾子を付けて定義しなければいけません。

D言語ではObjectから任意のクラスへのキャストが不正なものであった場合は結果がnullになるのでまずnullになっていない(不正な変換ではない)かをチェックします。 そして比較のコードを書くようになります。

immutable class

immutable class IC {
    int x;
    this (int x) {
         this.x = x;
    }
    override bool opEquals(Object o) {
        auto ic = cast(IC)o;
        if (ic is null) return false;
        return x == ic.x;
    }
}

このように定義した場合

Error: function dmatch.core.parser.AST.opEquals does not override any function, did you mean to override 'object.Object.opEquals'?

というエラーメッセージが出ます。原因はimmutable classとした場合immutableが付いているので実際にはbool opEquals (Object o){}でなくなってしまうためobject.Object.opEqualsをオーバーライドすることが出来ないためです。そのため、この場合はclassの定義自体を

class IC {
    immutable int x;
    this (int x) immutable {
         this.x = x;
    }
    override bool opEquals(Object o) {
        auto ic = cast(IC)o;
        if (ic is null) return false;
        return x == ic.x;
    }
}

と変更してやると動くようになります。 僕はこれでハマったのですが lempiji@思秋期 (@lempiji) | Twitterさんにこの解決法を教えていただき解決することが出来ました。ありがとうございました。

LinuxでCPUの一つが常時使用率100%になる問題

一部のハードウェアにおいて、kworkerが一つのスレッドをほぼ専有してしまうことがLinuxでは結構前から度々起きているようです。症状も様々で、有線LANを使うと発生すると言うもの、動画編集をすると発生すると言うもの、何もしなくても発生すると言うものなど様々なものがあるようです。 対症療法的でしかないのですが、一応解決策はあるのでメモしておきます。

grep . -r /sys/firmware/acpi/interrupts/

この中でenabledであり値が異様に高いものがあると思います。 それをrootで、

echo disable > /sys/firmware/acpi/interrupts/(先ほど見つけた値が異様に高いファイル) 

とするとCPU利用率が低下します。

自動化

ただこれを毎回起動するたびにやるのは面倒なので自動化します。

#!/usr/bin/zsh
echo disable > /sys/firmware/acpi/interrupts/(先ほど見つけた値が異様に高いファイル) 

などのような内容のシェルスクリプトを書き、chmodで実行可能にして/usr/local/binなどのパスが通っているディレクトリに配置します。

systemdの場合

[Unit]
Description = disable /sys/firmware/acpi/intterupts/gpe13

[Service]
#書いて配置したスクリプトに合わせてパスを変える
ExecStart = /usr/local/bin/disableGPE13
Type = simple
[Install]
#多分multi-user.targetで無くてもいい
WantedBy = multi-user.target

のようなserviceファイルを書いてdisableGPE.serviceなどの名前で/etc/systemd/systemディレクトリに配置したあと

systemctl daemon-reload
systemctl enable disableGPE

とroot権限でコマンドを打てば次回起動時から自動で実行してくれます。

upstartの場合

/etc/rc.localに

#gpe13は例
echo disable > /sys/firmware/acpi/interrupts/gpe13

などとexit 0の前に追記するだけで次回起動時から自動で実行してくれます。

高専カンファ行ってきました

高専カンファという高専生などによる勉強会に行ってきました。僕は今までこの手のイベントに参加したことが無かったのですが、香川から比較的近い明石で開催されるということもあり参加させていただきました。 LTが予想以上に面白く5分間という時間がとても短く感じられました。 同じロボコニストの方とも知り合え、互いの活動についての情報交換もでき、良い影響を与えられました。 近いうちに発表者として高専カンファに参加できるよう技術を高めていきたいです。

Arch Linuxをインストールした

今まではLinux Mintを使っていたのですが、pacmanが使いたくなってArch Linuxに変えました。 Windows10,Ubuntu,Arch Linuxのマルチブートにしましたが、予想よりは簡単でした。 ddでUSBにisoを焼く際に間違えてHDDに焼いてしまい構築していたWindows環境とUbuntu環境をぶち壊すとかありましたがインストールは思ったよりは苦労しませんでした。 今まで使ってきたLinux Mintと違い、かなり自分でやらなくてはいけない部分が増えましたが結構楽しいです。 dmdやdubもpacmanで取ってこれますし、かなり楽で嬉しいです。