今回のネタは、時々「あ~やっちまった」となるお話。
Windows Serverでログインしたまま(そして大抵は何かアプリを動かしたまま)のセッションに再接続しようとすると、たまにこんなエラーが出て接続させてくれないことがある。
「リモート デスクトップ サービスが現在ビジー状態のため、実行しようとしている操作を完了できません。しばらくたってからもう一度試してください。他のユーザーはログオンできます。」
ちなみに英語版のエラーメッセージはコレ。
「The task you are trying to do can’t be completed because Remote Desktop Services is currently busy. Please try again in a few minutes. Other users should still be able to log on.」
この問題が出てしまった時の対処法は、
「Adminユーザーでログインして該当ユーザーを強制ログアウト」
これが一番。というか、実質的にはコレしかない。
え、保存していないデータ?セッション切る前に保存していなかった方が悪い。
だってWindowsよ?いつ落ちてもおかしくないでしょ?それぐらい覚悟してるよね?
・・・え、鬼畜過ぎるって?
でもこんな風に割り切りでもしないとどうにもならないのも事実なワケで。
さくっと強制ログアウトしてしまいましょ。
◇
さて、頻度は低いとはいえ一度ブチ当たってしまうと状況次第では(精神的、或いは時間的)ダメージが結構大きいこのトラブル。
一番アレなところは、エラーメッセージが実態を全く正しく表していないことなのではないかと。
というのは、殆どの場合、問題なのはTermSvcs(Remote Desktop Services)ではなく、その上のセッションで動いているCsrss.exeがセッション接続要求に応えなかったからなんですな。
そもそもcsrss.exeって何かと言われると、カーネルとアプリケーション間のやりとり(システムコール等)を仲立ちするシステムサービス。Windows起動と共に開始され、サービス開始に失敗する(或いはユーザが間違って停止させる)とBSODで即落ちする、Windowsの基幹部品の一つ。
なので、アプリが起動する際には必ずこのcsrss.exeとのプロセス間通信が発生しているし、ユーザーがログイン・ログアウトする際、セッションが接続・解放される際にも然り、と。
ところが、デスクトップ用に作られてあまりセッション切断のことを考慮していないアプリがあると、セッションが切断された際にアプリとcsrss.exeの間でデッドロックが発生してしまうそうな。状況的には、カーネル側に対してはセッション切断を完了しているが、アプリ側のセッション切断完了は待ち続けているという。
仮にcsrss.exeがアプリにセッション切断を強制したらアプリが即ハングする可能性もあるので、さすがにそういう仕様にはなっていない。
この状態でもシステムコール等は正常に出来るし、アプリ自体は特に問題無く動き続けるが、csrss.exeの方は「セッション完了待ち」ステータスで居続ける為、新しいセッション接続要求に対して対応することが出来なくなってしまう。
#ちなみにWindowsServer2008/R2にはこのデッドロックが頻発する不具合(バグ?)があり、修正パッチが出ているものの、これも根本解決ではなくタイミング調整等でデッドロック頻度を下げているだけ、の模様。
◇
それじゃコレ、正しくお行儀良くセッション切断するアプリなら問題無いか、というとそう簡単な話でもないようで。
何しろ「純正」MS製のOffice等でもこのデッドロック状態が発生することがある、という話はぼろぼろ出てきているので。
不具合発生頻度が結構高くよくネタとして出てくるのはOutlookで、デカいメールボックスを抱えているようなユーザー。
Outlookのプログラム自体はこのセッション切断を考慮していないワケではないようなのだが、メールボックスに対して検索等の操作中だったり、裏でインデックシングが動いているような状況で切断すると、アプリ側のセッション切断がシステム側の要求に対して間に合わず、デッドロック状態に陥ることがある模様。
他にも、たまたまIO要求が高い状態でセッション切断すると、通常なら一瞬で終わる筈の処理がIOに引っ張られて待ち行列に入ってしまい、結果的にタイムアウトしてデッドロック状態になるというハメに陥ることも。
◇
ということで、元々「シングルセッション」「全権限制約無し」「起動中にセッション切断・再接続なんて考慮外」という世界で動いていたWindowsのデスクトップアプリを、Server上で動かすってのは意外とリスキーである、というお話でしたとさ。
まぁ自分の場合は「あっちゃーまたかよ」で済むので特に対策もせず使い続けているが、そういうのが許されない状況だったら、悪いことは言いません。
Server上でデスクトップアプリを動かすなんてことはやめといた方がいいです、はい。
そしてどうしてもデスクトップアプリを起動しなくてはいけなくなったら、終了するまでセッションはそのままで。
P.S.
個人的には出来はそんなに悪くないと思っているNT6.3カーネルなのだが、その中でも恐らく手癖として最悪なのがコレ
「IOのプライオリティが高い割に、IOと要求スレッドの並列化が十分になされていない」
ではないかと。
結果として、該当スレッドの処理内容とは関係無い筈のIOの待ちでスレッドが何故か一時停止したり、平行稼働出来る筈のIOが何故か順次稼働になってしまったり。
プライオリティを上げないとIO性能が頭打ちになるのは目に見えていたのでこの変更自体は正解だと思っているが(これからコンシューマーでもNVMe等が普通になっていくだろうし)、伴ってもう少し改善すべき箇所もある気がするのよね。