DRYな備忘録

Don't Repeat Yourself.

Docker Desktop がクラッシュしたり、Engine Starting からずっと動かなかったりする【Apple M2】

問題

  1. Docker Desktop (GUIアプリ)が起動中にクラッシュして落ちる
    • 当然、この状態でclidocker ps とかしても、「Engine not started」みたいなエラーを得る
  2. Docker Desktop が立ち上がったとて、Docker Engine のStartが一生終わらない

tl;dr

下記のforumで言及されている解放をいくつか試したが、結果的には

# Docker関係のすべてのプロセスを殺す
% ps aux grep docker
% pkill docker

# それでも殺せてないプロセスも殺しちゃう
% ps aux grep docker
% sudo kill -9 {pid}

んで、「Docker Desktop」アプリを起動し直すと、Docker Engine も含めて正常に起動した。

参考

上記forumの中の、dockerのプロセス全部殺せ、というのが最も有効であった。

ログ

Docker Desktop GUI アプリのクラッシュログ抜粋

Appleにreportするやつ。

Thread 0 Crashed:: CrBrowserMain Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib                 0x191c14744 __pthread_kill + 8
1   libsystem_pthread.dylib                0x191c4bc28 pthread_kill + 288
2   libsystem_c.dylib                      0x191b59ae8 abort + 180
3   Electron Framework                     0x111481768 node::Buffer::New(v8::Isolate*, char*, unsigned long) + 158392
4   Electron Framework                     0x11148199c node::OnFatalError(char const*, char const*) + 552
5   Electron Framework                     0x10bff34f4 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) + 592

マシンは十分にメモリを積んでいる(24GB)と思いつつ、いったん、OOMというメッセージがあるので、以下をトライ

  • メモリ食ってる他のアプリを停止
  • Docker Desktop のバージョンを v4.25.2 にアップデート
  • 念のため、PCをrestart

Engineが永遠に起動しない

Desktopは立ち上がったが、Starting Docker Engine からずっと動かない。Docker Desktopの右下の通知ベルのマークにエラーの表示があったため調べると、

Kernel Triage:
VM - pmap_enter failed with resource shortage
VM - pmap_enter failed with resource shortage
VM - pmap_enter failed with resource shortage
VM - pmap_enter failed with resource shortage
VM - pmap_enter failed with resource shortage

[091:19:56:46.565][E] dockerd died before the API started up: exit status 1

という表記があった。

右下のベルのマークにエラーの表示があった

これを参考にググると、

  1. Docker Desktop quit unexpectedly version · Issue #6056 · docker/for-mac · GitHub
  2. Infinite loop when starting docker after update. · Issue #6260 · docker/for-mac · GitHub
    1. Docker Desktop 4.6.1 for Mac Won't Start - #10 by khal3d - Docker Desktop for Mac - Docker Community Forums

などがヒットした。上記のリンク 2-a が直接の参考になったforumのポストであった。

備考

  • 明日からまたパワポを書く仕事に戻る
  • パソコンの黒い画面を見ているほうが落ち着く自分を強く感じる
  • しかし、給料などを考えると、苦しみながらパワポを書いたほうがいいという現状に、ここのところずっと悩んでいる
  • 早く抜け出したい

DRYな備忘録として

Twitter API v1.1を利用する箇所が失敗しているので調査・対応ログ

背景

もうかれこれ10年*1開発が続いているChrome拡張*2があり、このCI/CDの結果報告にTwitterAPIを用いている。また、ユーザにとっても、Chrome拡張上でTwitter認証を行い画像付きツイートを行える機能を提供している。

今回、この機能が以下のエラーを吐いて失敗している。どうやら、Twitter API の「アクセスレベル」関係でコケているようだ。

そらそうだ。10年ぐらい前からずっとv1.1だもんなぁお前

Web Store TEST · KanCraft/kanColleWidget@0588aa7 · GitHub

Error: [
  {
    message: 'You currently have access to a subset of Twitter API v2 endpoints and limited v1.1 endpoints (e.g. media post, oauth) only. If you need access to this endpoint, you may need a different access level. You can learn more here: https://developer.twitter.com/en/portal/product',
    code: 453
  }
]

調査

  • 認証は動いている模様。つまり検索などが走りすぎており、止まっているのだと思われる

Chrome拡張内で検索が走る部分のNetworkログ。たしかに失敗している

ビンゴ

問題の整理

  • まず、Twitter API v2 に対応したいのは山々だが、機能を回復させるのが先決
    • v2を利用したところで、上記に言われるように、無課金では動かんだろうし
  • また、Chrome拡張側でTwitterAPIがコケたときに、他の機能も利用できない状態になっているのはけしからん(下記画像参照)

Twitter検索が走り、失敗するとポップアップ画面のレンダリングごとクラッシュしている。
誰だこんな雑な実装したのは

対応

  1. TwitterAPIがコケている状態で、他の機能を心中させないよう修正
  2. Twitter API へ、最低限の課金をしようと思ったが、$100/monthという値段を見てビビった
    • ので、定期的に検索をかけて、どこかにデータを蓄積し、厳密にはリアルタイムではないがこれを配信するように修正したい

修正

(1)

github.com

(2) 別のrepositoryを立てて、GitHub Actionsで4時間おきとかにTwitter検索叩いて、結果をrepositoryにcommitするようにすればよかろう。後日やる

DRYな備忘録として

お名前ドットコムからGoogle Domainsへのドメイン移管ログ

tl;dr

support.google.com

学び

  • ドメイン移管は、ドメイン管理事業者同士のやりとりで完結する
  • ドメイン移管は、移管事業者が、移管事業者へ要請を送ることでトリガーされる
  • その際に必要なものは、移管事業者が発行する「認証コード」ないし「Authコード」のみである

注意

  • お名前ドットコムにおいて、移管に必要な「認証コード」ないし「Authコード」を得るとき、「移管」などのキーワードでメニューを検索してもヒットしない
  • ドメインドメイン詳細 → Authコード表示、が正解

雑感

  • サービスをつくるのはたのしい

DRYな備忘録として

GAEのデプロイが失敗する: ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build xxxxx status: FAILURE

問題

趣味として、所属している社会人アメフト部の出欠確認・備品管理アプリをスクラッチで書いているのだけれど、あるときGitHub Actionsで動いている自動化デプロイが、以下のエラーを出して失敗していた。

# 前略
Beginning deployment of service [dev]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 44 files to Google Cloud Storage               ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [dev]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build xxxxxxx status: FAILURE
An unexpected error occurred. Refer to build logs: https://console.cloud.google.com/cloud-build/builds;region=asia-northeast1/xxxxxxx?project=1111111111
Full build logs: https://console.cloud.google.com/cloud-build/builds;region=asia-northeast1/xxxxxxx?project=1111111111

調査

このログから分かることは

  • ソースコードを Cloud Storage に上げるところまでは成功している
  • Cloud Build で何らかのエラーが出ているが、詳しくはログを見ろ

ということなので、提示されているURLのログを Cloud Console で見に行くと、

Step #2 - "build": Status: Downloaded newer image for asia.gcr.io/gae-runtimes/buildpacks/google-gae-22/go/builder:go_20230305_RC00
Step #2 - "build": asia.gcr.io/gae-runtimes/buildpacks/google-gae-22/go/builder:go_20230305_RC00
Step #2 - "build": ===> ANALYZING
Step #2 - "build": ERROR: failed to initialize analyzer: getting previous image: getting config file for image "asia.gcr.io/triax-football/app-engine-tmp/app/dev/ttl-18h:latest": GET https://storage.googleapis.com/asia.artifacts.triax-football.appspot.com/containers/images/sha256:xxxxxxx?access_token=REDACTED: unexpected status code 404 Not Found: <?xml version='1.0' encoding='UTF-8'?><Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Details>No such object: asia.artifacts.triax-football.appspot.com/containers/images/sha256:xxxxxxx</Details></Error>
Finished Step #2 - "build"
ERROR
ERROR: build step 2 "asia.gcr.io/gae-runtimes/buildpacks/google-gae-22/go/builder:go_20230305_RC00" failed: step exited with non-zero status: 1

Cloud Storage に格納されているはずの「previous image」が無くてコケているように見える。 で、該当する Cloud Storage のbucketを見に行くと、確かに何も無いので、そりゃコケるわな、という気持ち。

原因

  • 年末大掃除のときに「まあ大丈夫やろ」という気持ちで14日以上のエンティティは全部削除されるようにした気がする。

してたわ

対処

  • Previous Image を削除しちゃっているので、同じCDを回してももちろん同様の理由で失敗する。
  • 原理的には、base image(GAEなので "runtime")とソースコードさえあれば、previous image を参照せずともアプリケーションのイメージをbuildできるはずである。
  • したがって、gcloud app deploy で、previous image を参照しないオプションが無いか、調査し、--no-cacheというオプションを発見した。

--cache

Enable caching mechanisms involved in the deployment process, particularly in the build step. Enabled by default, use --no-cache to disable.

gcloud app deploy  |  Google Cloud CLI Documentation

ビンゴ

なので、いったん手元で

 gcloud app deploy ./app.yaml --no-cache # 以下もろもろ略

としたらデプロイはできた。

原因に対する解決

  • 上記と同様に、GitHub Actions 上の CD においても --no-cache を指定すれば、Cloud Storage で何が起きてもデプロイできるのは想像がつく
  • --no-cache のdownsideとしてはもちろん時間がかかることがあるはずなので、logを確認すると、このプロジェクトは軽いので、
    • --cache = 1分30秒
    • --no-cache = 2分00
  • Pricingは、$0.003/分、なおかつ無料枠は120分/日 Cloud Build pricing  |  Cloud Build Documentation  |  Google Cloud

ということで、このプロジェクトに関しては --no-cache の対応 + Cloud Storage ではもっと早期に自動削除しちゃってよさそう。(7日削除にした)

以上

DRYな備忘録として

Club TRIAX では、メンバー/スポンサーを募集しております!

ちなみに私の役割は「デジタル担当」で、練習場にはほとんど行きません。そういう多種多様な関わりを通じて、仕事や人生そのものを充実させられる、魅力的なチームです。ご興味ある方は、ぜひお声がけください!

www.triax.football


cgoの中で#ifdefのようなプラットフォーム分岐をしてはいけない:clang: error: unsupported option '-fopenmp'

このエントリはGoのカレンダー | Advent Calendar 2022 - Qiitaの13日目です。多種多様なGoに関する記事を見ることができて、とても刺激になってます。ありがとう、クリスマス。ありがとう、アドベントカレンダー。当方はというと、最近ふつうにハマった問題の共有をしたいなと思います。

問題

cgoを使ったパッケージを開発中に、プラットフォームに依存したCフラグなどを渡す必要があり、cgoの中で #ifdef __APPLE__#ifdef __FreeBSD__ を書くものの、正しく分岐されず間違ったプラットフォームに間違ったビルドフラグが渡されるような挙動を観測した。

先に結論

  1. #cgoディレクティブはgoがCをコンパイルするよりも前に評価される。
  2. したがって、Cのプリプロセッサ#if#ifdefなど)により#cgoを分岐しようとしても、前もって評価されてしまうため、#cgoディレクティブに書かれたものが当該プラットフォームにとって正しくなければ掲題のようなエラーを吐く。
  3. これを避けるために、Goのファイル構成の段階で//go:buildないしxxxx_unix.goなどのファイル名suffixを使ってcgoへ渡す前に分岐しなければならない
  4. 雑にChatGPTにエラーメッセージを投げるの、勢いづけにめちゃくちゃ良かった!

追記





以下、ログなので読まなくていいです。メリークリスマス!★



ログ

  1. FreeBSDで起きている問題の認識と解決の方向性
    1. 長いことメンテしている自作のGoライブラリがあるんですが、こちらで、1年以上前からFreeBSDのCIがコケていることが観測されていた。
    2. CIの失敗ログを見ると、"ld-elf.so.1: /usr/local/lib/libtesseract.so.5: Undefined symbol "__kmpc_global_thread_num" というエラーメッセージとともにコケていることが分かった。
    3. __kmpc_global_thread_numとは、どうやら、OpenMPという並列計算を可能にするAPIを提供するライブラリに定義される定数のもよう。
    4. libtesseract.soOpenMPによって定義される定数を見に行こうとして、リンクされておらず困っているのだと推察。
    5. どうやら、LDFLAGSなどに-fopenmpを与えれば、解決しそうなので、Goのimport "C"をしているファイルの冒頭にフラグを追加すればよさそう。
  2. openmp問題の解決により新たに生じた問題
    1. 前述の通り、Goのimport "C"をしているファイルの冒頭に-fopenmpのフラグを追加した。⇒Fix test for vagrant · otiai10/gosseract@9be0318 · GitHub
    2. GitHub-hosted runners にpreinstallされているVirtualBox+Vagrantを利用したFreeBSDのテストは、通るようになった。
    3. 一方で、macOS上のテストは掲題のエラーとともにコケるようになった。
    4. Goのimport "C"をしているclient.goでは、#if __FreeBSD__ >= 10 を用い#cgoに与えるフラグを出し分けしているはずなのに、ナゼ...?
  3. Goファイルにおける#cgoディレクティブの振る舞いに関する気付き
    1. #ifディレクティブの書き方が良くない可能性に仮説を持ち、#ifdef __APPLE__#ifdef __FreeBSD__ に書き直してテストするが、同じ結果を得る。
    2. __APPLE____FreeBSD__などのマクロ定数が定義されていない可能性に仮説を持ち、gcc -E -dM - </dev/nullprintfデバグで確認するが、残念ながら__APPLE__は存在し__FreeBSD__は存在しない、正しい結果を得るものの、テストの結果は同じである。
    3. #define __APPLE__ 1#undef __FreeBSD__を冒頭に挿入しても、#ifdef __FreeBSD__のブロックへ突入するような挙動で、同じ結果を得る。
    4. この時点で、C/C++プリプロセッサが評価されるタイミングと、#cgoが評価されるタイミングが異なる可能性に気づく。Special Thanks id:moriyoshi
  4. Goファイルのレイヤでプラットフォーム依存のコードを分割し、解決を得る
    1. FreeBSDに与えたいLDFLAGSの定義は、preprocess_freebsd.goというファイルに定義し、それ以外に与えたいLDFLAGSはpreprocess_x.goというファイルに定義することで、解決した。
    2. 本件における最終成果物 ⇒ Separate Go files to control platform-specific Cgo flags · otiai10/gosseract@060b832 · GitHub

実際に上記のプロジェクトでコケていたCIのログ

上部は実際のコードだが、下部はデバグのために仕込んだコード。
①のセクションでは#ifdefで分岐がされていない?ように見える

参考資料

リファレンス

参考

雑感

自作Slack-botにChatGPTを組み込んだので話が早い...!

当ブログとは関係無いんですが、GoからOpenAI ChatGPTのAPIを利用できるためのAPIクライアントを作ったので、スターやissueくれるとうれしいです!

github.com

DRYな備忘録として

HTMLのformタグのaction属性にqueryパラメータを設置したが、サーバ側で取得できていない

問題

クライアント(HTML)側

<form method="GET" action="/form/submit?nickname=otiai10">
  <input type="submit" value="送信" />
</form>

サーバ(Go)側

func HandleFormSubmit(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf("nickname: %s", req.URL.Query().Get("nickname"))
}

ブラウザで見える出力

nickname: 

つまり来てない。

検証方法

  • ブラウザのURL欄に直で、
https://自サーバ/form/submit?nickname=otiai10

と入力して訪問。するとブラウザでは

nickname: otiai10

と表示される

原因

formタグをGETメソッドで使用するとき、action属性に付加する ?nickname=otiai10 などのqueryパラメータは送信時に無視され、inputタグを見てparameterが再構築される。

stackoverflow.com

解決

  • action属性の中でqueryを使うな
  • inputタグ(e.g. type="hidden")を使え
-  <form method="GET" action="/form/submit?name=otiai10">
+  <form method="GET" action="/form/submit">
+   <input type="hidden" name="nickname" value="otiai10" />
    <input type="submit" value="送信" />
  </form>

雑感

  • input[type=hidden]なんて久しぶりに書いた。
  • 上記は検証用ゆえに、form[method=GET]を使っていたり、任意の入力値をサニタイズせずにブラウザに表示したりしており、商用コードとしては問題あるので、ご注意ください。
  • 世の中はAIだのブロックチェーンだの言っているが、俺はまだ世界の片隅でHTMLを書いてる...

DRYな備忘録として

GitHub Actions からの deno deploy が失敗する: Error: The deployment failed: Relative import path "$fresh/server.ts" not prefixed with / or ./ or ../

問題

以下のようにデプロイのGitHub Actionsを設定したが、掲題のエラーを得る。

    steps:
      - name: Clone repository
        uses: actions/checkout@v2
      - name: Upload to Deno Deploy
        uses: denoland/deployctl@v1
        with:
          project: "fresh-youtube"
          entrypoint: "./main.ts"

github.com

原因

解決

    steps:
      - name: Clone repository
        uses: actions/checkout@v2
      - name: Upload to Deno Deploy
        uses: denoland/deployctl@v1
        with:
          project: "fresh-youtube"
          entrypoint: "./main.ts"
+.        import-map: "./import_map.json"

github.com

雑感

  • deno、ノーストレスでTypeScriptが書けるのがよい。
  • あと、dependenciesのimportが直接的かつ明示的なのがよい。
  • 仕事でコード書かないからこそ、いつも触ってない技術をもっと積極的に触っていかなくてはならないと感じた。
  • ということで fresh framework で使えるめちゃくちゃ良い感じのコンポーネント作ったのでぜひStarしてあげてください。

github.com

DRYな備忘録として