名言。
前任者呼びもじわじわくる。

ウマ娘関連のネタが多いでしょうか
名言。
前任者呼びもじわじわくる。
facebook に殴り書きしたメモが好評。
サーバサイド JavaScript が語られる時、大抵は node の話が出てきて
PC 上でも JavaScript が動く→サーバ開発用としても使える
みたいなストーリーになっているのだが、 現実的に言えば、そのままでは使えない。
思い出して欲しいのだが、そもそも JavaScript は非同期のクセの強いスクリプト系言語だ。
これだけでも使い勝手が悪い上、エラーが出るとプログラム自体が停止してしまう、というおおよそサーバー開発用言語としては不向きな弱点を持っている。
この弱点を回避するためには、停止した際に復旧する仕組みなどが必要なのだが、最近では pm2 の評判がいいようだ。
ところで、pm2 をグローバルでインストールするとき、sudo つけないとできなくない?
実用的にも
sudo npm install -g pm2
でいいと思うんだが。(詳しい使い方はこの記事あたり参照)
ちなみに pm2 の p はプロセスの p でしょう。
(ここでいうことではないかもしれないが、特異な言葉の使い方は周囲から理解されにくくなるのでやめた方がいいと思う。何言ってるかわからん人はリンク記事読んでください。通常、「スレッド」というべきところを「プロセス」と言っちゃているので、内容にはそそられるところがあったが、結局、読むのをやめてしまったっていう話です)
本番で使うなら、SSL 化は必須。
これも(今となっては)使えない書き方している記事は多い。
Express 3 以降は以下のように書き方になるらしい。
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('sslcert/server.key', 'utf8');
var certificate = fs.readFileSync('sslcert/server.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();
// your express configuration here
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(8080);
httpsServer.listen(8443);
StackOverFlow より。
秘密鍵 server.key とサーバー証明書 server.crt を sslcert というフォルダに配置して読み込むだけでいい。
こういうことができる node 環境は素晴らしいと思う。
しかし、こういう情報を海外筋から入手しないといけないというのは少々いただけない。
少々、愚痴っぽいテイストが入っているので、この際だから言わせてもらうと、ある程度、この業界でちゃんと生きていきたければ
C と Unix
に関しては、イロハ+α 程度のスキルは身につけておいてほしい。
なんで、突然、こんなことを言い出したかといえば、某会社経由で「C や Unix ? あー、彼なら、余裕っすよ。経験あります」という触れ込みで配属された人が、まるっきりできていなかったから(笑・・えない)。
(続く)
あまり作る機会がないのだが、Mac アプリ用のインストーラーとして pkg 形式というものがある。
アプリそのものの場合、公証を受けなくてもユーザーが右クリック→「開く」でインストさせることはできるが、インストーラーの場合、デフォルトでは
オーナー root :グループ wheel
でインストされるせいか、この辺はキビしく、公証を受けていないと
「このパッケージは、このバージョンの macOS と互換性がありません」
という無慈悲なアラートとともにインスト自体がストップしてしまう。

だから、配布したい場合、公証まで受ける必要がある。
で、pkg 形式のファイルの作り方だが、現在だと『Mac用installerの作り方』 がまとまっているようだ。
ただ、この記事、.app が前提となっていて、コマンドラインツールでは全く通用しない。
説明も、もっぱら手順のみでコマンドの意味もまったく解説されておらず、ある程度のスキルを持った人はイライラすると思う。
追記の記事が一番確実。(ワイも Xcode 上で実行できないか試したが、記事のようにコマンドラインからビルドするのが確実なようです。しかし –timestamp というフラグは言われないと気が付かない)
だが、その他のコマンドがいささか古いのでアップデート。
まず、XXX.plist をつくる。
pkgbuild --analyze --root build/pkgroot hoge.plist
中身を見るとわかりますが、コマンドラインツールの場合、hoge.plist はほぼ何の有益な情報も記入されてないです。次のコマンドのために形式的に必要なのでは?と思います。
次はこれを使って .pkg を作成。
pkgbuild --root build/pkgroot --component-plist hoge.plist --scripts scriptDir --identifier id --version version --install-location "/" hoge.pkg
お次は hoge.pkg に(インストーラーの方の)署名。
productsign --sign "Developer ID Installer: team name" "hoge.pkg" "hoge2.pkg"
この時点でも公証は受けられる。
この時の password は apple ID 本体のやつではなくて、サードパーティアプリの二段階認証用のものを使う。
ない場合は(ほとんどの場合、ないと思うが)、appleID のページに行って作成。
xcrun notarytool submit hoge2.pkg --apple-id "hoge@hoge.com" --password 1234-5678-abcd-efgh --team-id 1234ABCD --wait
それほど大きくないソフトであれば数分で以下のメッセージが返ってきます。
Processing complete
id: 1234678-abcd-4f44-86ae-792c54d13965
status: Accepted
その他事項はまずはこの確認やってからでいいと思う。
ネットに落ちている情報は古いことが多く(この記事だっていつかは陳腐化するでしょう)、一回で決まることはまずないと思うので。
追記:英語になるがこの記事 や この記事(こちらは日本語)なども参考に。
今までよく分かってなかったプロセス・スレッド・同期・非同期云々を今のうちにまとめておこうと思い、ネット上を散策。
とりあえず、ここから始まる書き物を読んでいたのだが、読み進めるうちにちょっとイライラしてきた。
なんでこの人は、Xinu というそれほどメジャーとは言えないような環境でテストしているんだろうか?
今、現在、この仕事の評価が即できるほどの力量を持ち合わせていないので、なんとも言えないのだが、現在、使いやすい環境を一つ選んでサンプル載せた方が利便性という意味では良いと思う。
Linux, MacOS, Windows なんでもいいでしょ。
その一方で、ネットには(まとまっていないものの)「おお!」と呻きたくなるような有用なサンプルコードが落ちている。
文句ばかり言っても始まらないので、それらを収集して、暫定的なコメントをつけていく。
まずは、以下のサンプルコードを実行してみよう。
fork.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
printf("PID=%d\n", pid);
exit(0);
}
実行形式のファイルを得るのは、Linux or MacOS なら、上のコードをテキストファイルに書き込んで
gcc fork.c -o fork
でいい。それだけ。
実行すると
% ./fork
PID=80644
PID=0
という結果が得られる。
この PID というのは 「システム管理者が端末から ps コマンド叩いて、何やらやっている PID のこと?」と思うかもしれないが、その通り。
次に以下のコードも同様に実行。
fork2.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
printf("PID=%d %d\n", pid, getpid());
getchar();
exit(0);
}
同様に実行すると getchar() でこのプログラムは入力待ちとなり一時停止する。
この状態で他の端末から ps してみよう。
% ps
PID TTY TIME CMD
48613 ttys000 0:00.17 -zsh
31547 ttys001 0:00.90 /bin/zsh -il
85863 ttys001 0:00.02 ./fork2
85865 ttys001 0:00.00 ./fork2
予想通り、PID はあの PID だった。
なお、「通常子プロセスは exec コマンドと組み合わせて他のプログラムを起動するときに使われる」と説明されているが、具体的なコードがない。
このわかりやすい例が StackOverFlow にあったので、あげておく。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main (void) {
pid_t processId;
if ((processId = fork()) == 0) {
char app[] = "/bin/echo";
char * const argv[] = { app, "success", NULL };
if (execv(app, argv) < 0) {
perror("execv error");
}
} else if (processId < 0) {
perror("fork error");
} else {
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}
ところで、このコードは参考(下参照)から拾ってきたが、この著者の説明は明快で、こちらの記事でプロセスとスレッドについて実に簡潔に説明している。

普通はこういう理解だと思う。
最近このブログでは NativeMessaging を取り上げたが、NativeMessaging は通常「プロセス間通信」と呼ばれていると思う。
一つのプロセスは chrome 拡張の JavaScript プログラム、もう一つのプロセスは host のネイティブアプリ。
なんで大学教授のやつがイライラしたかと言えば、通常はスレッドというべきものをプロセスと呼んでいたから。
内的な整合性が取れていればそれでもいいんだが、有用性でいうとあれ?って感じ。率直に言えば「使えない」。昨今のアカデミア軽視の風潮はこんなところから来ているのかもしれない。
そういうわけで次はスレッド。
スレッドを生成した側のメインスレッドが先に終了して、同時にスレッドが意図しないタイミングで強制終了すると想定しない状況に陥るかもしれません。ここまでの例では、メイン関数側がスレッドの処理時間よりも十分に長い時間を待機させるようにしてそれを避けていましたが、メイン関数側は、生成したスレッドの終了するタイミングの長短にかかわらずスレッドの終了を待ち合わせるべきでしょう。
そーそー。しかし、わかりやすいですね。
そして提示されていたサンプルがこちら。
threadjoin.c
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void *th_func(void *arg) {
puts("thread created");
sleep(10);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
if (pthread_create(&th, NULL, th_func, NULL) == 0) {
puts("Main thread");
pthread_join(th, NULL);
puts("Main exit");
}
}
sleep に与える変数を変えると確かにその間もメインスレは待ってますね。
すげ。
pthread に相当する obj-c の機能はないかとあれこれ物色していたのだが、セマフォ semaphore がそれに該当するらしい。以下のサンプルを作成。
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
dispatch_semaphore_t syncSemaphore = dispatch_semaphore_create(0);
// 非同期タスクの実行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 何らかの処理
NSLog(@"非同期タスク実行中");
// タスクが終了したら、セマフォのカウンタを +1 にする
dispatch_semaphore_signal(syncSemaphore);
});
// セマフォのカウンタは当初 -1 なので、メインスレッドは停止している
dispatch_semaphore_wait(syncSemaphore, DISPATCH_TIME_FOREVER);
NSLog(@"非同期タスク終了");
return 0;
}
これ、セマフォがないと、メインスレッドの方が先に終了してしまい、必ずしも dispatch_async が処理されるとは限らない。
「非同期処理の同期をとる」のような時に使うらしい。
実行結果は期待どおり
非同期タスク実行中
非同期タスク終了
Program ended with exit code: 0
となる。
おまけ。この記事が参考になった。
参考: