2023-11-01 (Wed)

行儀の悪い Python ライブラリ

某実験施設では測定データを取り出すのに独自の Python パッケージ(C ライブラリの wrapper)を利用する。このパッケージのソースコードは非公開である。仕様書には multithread 非対応と書いてあるが、スレッド並列化のみならず fork によるプロセス並列化でも失敗する。パッケージが提供するメソッドを呼ぶタイミングが同時にならないようにコードを書いてもダメで、親プロセスで一度でもメソッドを呼んでしまうと、関係するオブジェクトをすべて破棄したあとで fork したとしても、子プロセスからメソッドを呼んだ時に不規則にクラッシュする。Spawn なら大丈夫だが、コードが複雑になるし立ち上げが遅いので嬉しくない。パッケージが行うタスクの性質上 fork できない理由がなさそうなのだが、開発元に問い合わせても「非対応」の一点張りで詳細を教えてくれない。

何らかのリソースリークが発生している懸念さえあるので、stracelsof -i にて挙動を解析した。このパッケージは実験メタデータを取得するために施設内の MySQL サーバと通信するのだが、利用が終わってオブジェクトをすべて開放したあとでも、接続が開放されないことが分かった。この socket が fork によって複製されると、複数の子プロセスから同一のコネクションを通じて一気にサーバに話しかけるので問題が生じるのだ。

そこで、psutil.Process().connections で当該コネクションの file descriptor を取得し、fork 前に強引に os.close() してみた。Fork 先では無効な socket にアクセスしようとして死ぬかと思いきや、なんと適切にソケットを開き直すことが分かった。パッケージ内のグローバル変数として socket をキャッシュしており、それが閉じていれば/失敗すれば開き直すという実装になっているのかなと想像するが、パッケージのコードが非公開なのでこれ以上は分からない。Undocumented な挙動なので production code に使うこともできないが、興味深い体験だったし、psutil という便利なパッケージのことを知れたのでよしとする。

Qt アプリの HiDPI 対応

Linux で Spotlight 的な PDF 検索を実現するため、recoll を入れてみた。その GUI のフォントが小さすぎるので、この記述 に従って、

export QT_AUTO_SCREEN_SCALE_FACTOR=1

したら良い感じになった。

読んだ

  • カクヨム「異世界⇔地球間で個人貿易してみた」 を最新話まで読んだ。
    いくらライトノベルとはいえ、女性キャラの体型描写がしつこく繰り返され、しかもどのキャラも同じような体型(巨乳)なのでうんざり。しかし、それにさえ目をつぶれば、異世界貿易モノとしては安定した出来。現実社会と異世界がつながる系のファンタジーは、現実社会の制度や法律(税金とか)に準拠させようとするとキリがないし展開が制限されてしまうから、うまくウソをつかないといけないのだけれど、その匙加減に失敗している作品が多い。本作品はうまく行っているほうだと思う。