2010年1月25日月曜日

Firefox 3.6 で JavaScript が正しく動作しなくなった場合

以下のワンライナーを使ってブラウザの判定を実施している場合、注意が必要。

/a/[-1]=='a'

Firefox 3.5以前では上記が"true"になるが、Firefox 3.6以降では"false"になる。

2009年11月12日木曜日

MacVim-KaoriYaのformat.vimを正しく動かす

※正確には、encoding=utf-8を指定したvimの話。

format.vimは、vimにおける禁則処理等の文章整形用のスクリプト。
MacVim-Kaoriyaの環境においては動作不備が確認される。
具体的には、インラインモードにて行末禁止文字を打ち込んだ場合、本来改行すべき桁数よりかなり前の桁にて改行される。(正確にはtextwidthに指定した数値の2/3の桁数)

これは、format.vimの内部処理にて、マルチバイト文字の表示幅として、文字のバイト数をそのまま用いているためである。
マルチバイト文字のバイト数は、encoding=cp932(windowsでのデフォルト)の場合は「2バイト」となり特に問題は起きないが、encoding=utf-8の場合、「3バイト」となるため、これをそのまま表示幅として用いることが出来ない。

これを回避するため、以下の様な修正を行った。

--- format.vim.org 2009-10-27 09:00:56.000000000 +0900
+++ format.vim 2009-11-12 17:13:28.000000000 +0900
@@ -686,17 +686,17 @@
   let back_count = 0
   let no_begin = s:GetOption('format_no_begin')
   let no_end = s:GetOption('format_no_end')
-  let curr_char = matchstr(a:curr_line, '\%'.a:curr_col.'c.')
+  let curr_char = matchstr(a:curr_line, '\%'.a:curr_col.'v.')
   let back_col = 0
   while 1
-    let prev_char = matchstr(a:curr_line, '.\%'.(a:curr_col - back_col).'c')
+    let prev_char = matchstr(a:curr_line, '.\%'.(a:curr_col - back_col).'v')
     if curr_char == ''
       let back_count = 0
       break
     elseif s:IsTaboo(curr_char, no_begin) || s:IsTaboo(prev_char, no_end)
       let back_count += 1
       let curr_char = prev_char
-      let back_col += strlen(curr_char)
+      let back_col += (strlen(curr_char) > 1 ? 2 : strlen(curr_char))
     else
       break
     endif
@@ -712,10 +712,10 @@
     " Too difficult to implement.
     return 1
   else
-    let curcol = col('.')
+    let curcol = virtcol('.')
     " v:charを入力した後で&textwidthを超える場合に改行位置の補正を行う
     let new_line = getline('.') . v:char
-    if curcol + strlen(v:char) > &textwidth
+    if curcol + (strlen(v:char) > 1 ? 2 : strlen(v:char)) > &textwidth
       let back_count = s:GetLinebreakOffset(new_line, curcol)
       " カーソル移動と改行の挿入を行う
       if back_count > 0

以上により、encoding=utf-8の環境においても、encoding=cp932の環境と同等の動作を期待出来る。

※ref : MacVim-KaoriYa (http://code.google.com/p/macvim-kaoriya/)
※ref : format.vim (http://www.kaoriya.net/doc/vim_script.html)
※source var : format.vim 1.7rc2 03-Mar-2007. in MacVim-KaoriYa 20091027


ここからはオリジナルの動作に対するコメント。
  1. 現状、textwidth値ジャストに行末禁止文字を入力すると、改行が実施されてしまう。
    本来であれば、textwidth値に収まっているのであるから、改行は不要の様に思う。
    ちなみに、gqコマンドであれば改行されない。
  2. 現状のアルゴリズムだと、textwidthを1バイトだけ超える、行末禁止文字「以外」の文字が行末に入力された場合に、正しく改行が挿入されないことになる。
    例えば、textwidth=10の場合に、"aあああああ"という文字を入力すると、最後の「あ」が改行されない。
    実質的にはtextwidthを超えているため、改行されるべきの様に思う。
    ちなみに、gqコマンドであれば改行される。

なお、(1)については、L:718の部分を、以下の様にすることで正しい動作が期待出来る。

-    if curcol + strlen(v:char) > &textwidth
+    if curcol + (strlen(v:char) > 1 ? 2 : strlen(v:char)) - 1 > &textwidth

(2)については、ASCIIの入力が若干絡むため、少しめんどくさい気がする。
こちらについては、追って検討したい。

2009年10月28日水曜日

スタイルシートにおける空URL指定の扱い

スタイルシートでバックグラウンドイメージの指定などに使うURL指定は、空指定した場合に参照元を引き継ぐ。(See, RFC 1808 Section 4)

空指定とは、URL()やURL('')のような指定。
参照元とは、cssファイルに記載している場合はcssファイルそれ自身で、JavaScriptでobject.style.backgroundImage等を操作している場合はJavaScriptがロードされているURLとなる。

つまり、"/hoge.css"の中で"background-image:url()"と記載すると、"background-image:url('/hoge.css')"のように解釈されるし、"/fuga.cgi"中のJavaScriptで、"document.style.backgroundImage='url()';"とすると、"document.style.backgroundImage='url(/fuga.cgi)'"のように解釈される。

このため、cssをcgi等で動的に生成している場合や、JavaScriptで動的にスタイルを変更している場合に、意図しない空指定が行われることで「無駄なhttp GET」が実行されることがある。
例えば、CGIの処理結果ページにJavaScriptが設定されており、その中で空URLが指定されるバグがあったとすると、当該CGIが2回GETされることになる。
ブラウザにもよるが「デバグ系のプラグイン」を動作させると、こういったGETが走らない場合が多く、原因究明でつまずきやすいため、URLを生成するルーチンには注意を払うべき。

2009年10月7日水曜日

FreeBSDで最新のportsを取得する方法

初回の更新処理
以下のコマンドを実行する。

$ portsnap fetch extract

二回目以降の更新処理
"/usr/ports"以下で、以下のコマンドを実行する。

$ make update

以上の手順は、portsnapコマンドを用いる方法(PORTSNAP_UPDATE方式)で、最も推奨される更新手順である。

ただし、OSのソースを取得する方法と同様に、csupを用いる方法(SUP_UPDATE方式)もある。
この場合、make.confに以下の記述を行えばよい。(/usr/ports/Makefile:166-170)

SUP_UPDATE=yes
PORTSSUPFILE=/usr/share/examples/cvsup/ports-supfile


また、cvsを用いる方法(CVS_UPDATE方式)もある。
この場合、make.confに以下の記述を行えばよい。(/usr/ports/Makefile:171-175)

CVS_UPDATE=yes

ただしこの場合、CVSROOT環境変数に適切な値を入れておく必要がある。

設定の優先順位は、SUP_UPDATE,CVS_UPDATE,PORTSNAP_UPDATEとなっている。
デフォルトはPORTSNAP_UPDATE。(/usr/ports/Makefile:166-190)

※source ver : FreeBSD 7.2 Release-p4

2009年10月6日火曜日

FreeBSDでOSの最新ソースを取得する方法(supファイルを書かずに)

まず、"/etc/make.conf"に以下の記載を追記する。

SUP_UPDATE=yes
SUPHOST=cvsup.jp.FreeBSD.org


次に、"/usr/src"以下で、以下のコマンドを実行する。

$ make update

動作としては、所定のsupファイル(ただしhostは上書き)を使って、csupコマンドを実行しているだけ。
参照しているsupファイルは以下の通り。(/usr/share/examples/etc/make.conf:186)

/usr/share/examples/cvsup/standard-supfile

ちなみに、上記supファイルのtag指定は以下のようにマイナーバージョンまでを含めている。(/usr/share/examples/cvsup/standard-supfile:52)

*default release=cvs tag=RELENG_7_2

そのため、取得できる「最新ソース」は、あくまでパッチレベルである点に留意すること。

より細かな設定については、"man make.conf" もしくは、/usr/share/examples/etc/make.confを参照の程。

※source ver : FreeBSD 7.2 Release-p4

2009年10月1日木曜日

Apacheプロセス数のチェック方法

駆動中のhttpdプロセス数のチェック
$ ps -a | grep httpd | grep -v grep | wc

プロセスリストからhttpdプロセスの数を数える。
"grep -v grep"しないと、"grep httpd"まで数え上げてしまう。
また、httpdは親プロセス+子プロセスで出てくるので、MaxClients等で指定した子プロセス数より1つ多くなる点に注意。

httpでのTCPコネクションのチェック
$ netstat -a | grep .http | grep EST | wc

httpポートでESTABLISHEDしているTCPコネクション数を数える。



定期的にチェックする場合は、以下の様にするのが楽。
$ while [ 1 ]; do ps -a | grep httpd | grep -v grep | wc; sleep 1;
done

※1秒ごとにコマンドを延々実行(B-Shell系)

セッションを張りっぱなしのクライアントを実現(つまり、ずっと処理中の子プロセスを生成)するには、以下の様にtelnetで直接叩くのが楽。
$ telnet www.server.com 80
ただし、Accept Filterを有効にしている場合、TCPはESTABLISHEDするが、子プロセスまで要求が渡らないため、httpd子プロセスは増えない。
Accept Filterを一旦解除するか、sleepするCGIを作成し、これをGETするのがよい。

Apacheの駆動プロセス数について

Apacheのプロセス数の制御は以下のディレクティブで行う。
  • ServerLimit
  • MaxClients
  • MinSpareServer
  • MaxSpareServer
  • StartServers
ServerLimitは、起動する子プロセス数の最大値を決める。
デフォルトでは200000。(/httpd-2.2.13/server/mpm/prefork/prefork.c:84)

MaxClientsは、駆動する子プロセス数の最大値を決める。
(preforkの場合、ServerLimitと同意になる)
ServerLimitより小さい数値である必要があり、デフォルトでは256。(/httpd-2.2.13/server/mpm/prefork/prefork.c:77)

MinSpareServerMaxSpareServerは、アイドルプロセス数の最小値、最大値を決める。
アイドルプロセスとは、クライアントからの要求を受ける前にあらかじめforkしておく子プロセス。
あらかじめforkしておくことで、要求発生時に素早く処理ができる。
MinSpareServerのデフォルト値は5 (/httpd-2.2.13/server/mpm/prefork/mpm_default.h:46)
MaxSpareServerのデフォルト値は10 (/httpd-2.2.13/server/mpm/prefork/mpm_default.h:40)

StartServersはApache起動後すぐ起動する子プロセス数。
MinSpareServerと同値にするのが通常だが、異なる値も指定出来る。
ただし、どのような値を指定しても、MinSpareServerとMaxSpareServerの間に収まるように調整される。
StartServersのデフォルト値は5 (/httpd-2.2.13/server/mpm/prefork/mpm_default.h:32)


子プロセスの総数は、MaxClientsより多くはならないため、処理中のプロセス数が増大すると、アイドルプロセスがMinSpareServerより少なくなる場合がある。(httpd-2.2.13/server/mpm/prefork/prefork.c:796 perform_idle_server_maintenance)
アイドルプロセスが0、つまり処理中のプロセスがMaxClientsに達すると、以下のエラーが出力される。
"server reached MaxClients setting, consider raising the MaxClients setting" (/httpd-2.2.13/server/mpm/prefork/prefork.c:867)

各ディレクティブの詳細は、apacheのマニュアルを参照の程

※動作モードはmpm_preforkに限る
※source ver : Apache 2.2.13