[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FDclone-users:00493] Re: .fd_history was lost



 しらいです。

In Message-Id <86wtdyeiml.knu@iDaemons.org>
        "Akinori MUSHA" <knu@iDaemons.org>さんwrites:
>  ホームディレクトリを NFS マウントして運用しているのですが、
> この環境ではファイルのロックがサポートされていないために、
> shell.c:savehistory() の Xfopen(file, "w") → lockfile() の
> ところで失敗し、そのまま Xfclose() されて ~/.fd_history が
> 空っぽになってしまいます。

 ふむ。確かに NFS では lock が効かないので link(2) 辺りを使
って疑似 lock をかけるのが定石ですね。
 最近の NFS は普通に lock がかかってしまうものが多いので忘
れていました。これは相手先の条件もあるので、やってみないこと
には lock 不能な file system かどうかは判断不能ですね。


> 1. 別にロックファイルを作る
> 2. open(2) の O_EXLOCK でアトミックにロックする
> 3. 追記モード(a, a+, r+)でオープンして truncate させない

 O_EXLOCK は BSD 固有の option なので余り適切ではなさそうで
す。
 また、2. と 3. とは lock 不能だった場合にコマンド履歴が保
存されないので、使い勝手としては truncate されてしまうのと大
差ないと思います。
 ちゃんとやるなら、fcntl lock に失敗した時点で link lock を
試すといった手法になるでしょうかね。


>  csh, tcsh, ash, bash (libreadline) などはファイルロック自体
> していないようでした。同じユーザで対話シェルを同時に起動または
> 終了するというケースはまれと見たからかもしれません。

 実際に .fd_history が壊れたという事例があったんで lock を
実装したんですが、余り気にしないでもいいということでしょうか
ね。
 そういうことであれば、fcntl lock で実装しておいて返り値は
無視するという実装でどうでしょうかね。

 blocking lock にしてるので、返り値を無視したところで lock
が有効な環境では普通に lock がかかる筈です。lock が無効な環
境でのみ、file の同時書込みに対応出来ないということで。
 link lock の実装は、作成した lock file の後始末が面倒なん
ですよね。割込まれた時とか異常終了した時とか考えると、そこま
で苦労して実装することもないかと。

# MHpopd の実装を見たら、わざわざ getmntinfo(3) 辺りを使っ
#て NFS かどうか調べてから lock かけてるらしい。何故そこま
#でする必要が...:-)

---- Cut Here ----
diff -u ../old/FD-2.08b/shell.c ./shell.c
--- ../old/FD-2.08b/shell.c	Thu Mar 30 00:00:00 2006
+++ ./shell.c	Mon Apr 10 22:45:35 2006
@@ -1630,12 +1630,7 @@
 	int i, j, size;
 
 	if (!file || !(fp = Xfopen(file, "r"))) return(-1);
-#ifndef	NOFLOCK
-	if (lockfile(Xfileno(fp), LCK_READ) < 0) {
-		Xfclose(fp);
-		return(-1);
-	}
-#endif
+	VOID_C lockfile(Xfileno(fp), LCK_READ);
 
 	size = (int)histsize[n];
 	history[n] = (char **)malloc2(sizeof(char *) * (size + 1));
@@ -1650,7 +1645,7 @@
 		for (j = i; j > 0; j--) history[n][j] = history[n][j - 1];
 		history[n][0] = line;
 	}
-	lockfile(Xfileno(fp), LCK_UNLOCK);
+	VOID_C lockfile(Xfileno(fp), LCK_UNLOCK);
 	Xfclose(fp);
 
 	for (i++; i <= size; i++) history[n][i] = NULL;
@@ -1684,16 +1679,11 @@
 
 	if (!history[n] || !history[n][0]) return(-1);
 	if (!file || !(fp = Xfopen(file, "w"))) return(-1);
-#ifndef	NOFLOCK
-	if (lockfile(Xfileno(fp), LCK_WRITE) < 0) {
-		Xfclose(fp);
-		return(-1);
-	}
-#endif
+	VOID_C lockfile(Xfileno(fp), LCK_WRITE);
 
 	size = (savehist > (int)histsize[n]) ? (int)histsize[n] : savehist;
 	for (i = size - 1; i >= 0; i--) convhistory(history[n][i], fp);
-	lockfile(Xfileno(fp), LCK_UNLOCK);
+	VOID_C lockfile(Xfileno(fp), LCK_UNLOCK);
 	Xfclose(fp);
 
 	return(0);
---- Cut Here ----

                                               しらい たかし