Consoleの文字化け対策 CoreCLR

昨日のテストで、文字化けしていましたが、これを対策します。

答えは簡単で、エンコードの問題でした。

まず、コンソールのエンコードを見てみます。

932、Shift-JISとなっています。これに対して、System.Consoleのエンコーディングを見てみます。

UTF-8となっています。つまり、UTF-8として出力されたものをShift-JISとして表示しようとしているので、おかしくなっていると考えられます。あわせてしまえばよいですね。一人でやってる分にはConsoleのエンコードを変えるという選択肢もあるかもしれません。ただ、そうしてしまうと個々の環境で設定が必要になってしまうため、コード側で対策しておきたいところです。なので、System.Consoleのエンコードを変えてみます。

var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
Console.SetOut(writer);

としたいところなのですが、実はこれだと動きません。

NotSupportedException
No data is available for encoding 932. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.

何やら、エラーがSystem.Text.Encoding.RegiterProviderメソッドを見ろといっています。ここの説明では

.NET Framework 4.61 つのエンコード プロバイダーが含まれています。 T:System.Text.CodePagesEncodingProvider、を行う、利用可能なエンコーディングでは使用できませんが、完全な .NET Framework に存在を.NET Framework 4.6です。既定では、.NET Framework 4.6のみ、Unicode エンコーディング、ASCII、およびコード ページ 28591 をサポートします。

この「のみ」にすこし違和感ありますが、日本語は含まれていないようです。28591は西ヨーロッパ言語 (ISO)ですね。というわけで、そもそも、日本語は既定でサポートされていません。デスクトップ同様のサポートを確保するためには、System.Text.CodePagesEncodingProviderを利用してねーという内容ですかね。このクラスには、Instanceという静的なプロパティが一つ。これをエラーの内容に従って追加してみましょう。

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
Console.SetOut(writer);

という感じにしてみました。いざ、実行!

あれ!きれいですね。何も出てこないとなるのですが、これはバッファにFlushがかからないために出てこなくなるようです。なので、AutoFlushを有効にしちゃいましょう。

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
writer.AutoFlush = true;
Console.SetOut(writer);

という感じにプロパティの設定を追加。再び!

無事に日本語を拝めました。注意として、ここの実装だけだと、強制的にShiftJISとしてしまうので、Linuxで動かしたときは、逆に文字化けしてしまう可能性があります。また、日本語ではないWindowsでも同じことが言えます。様々なプラットフォームで動かすためには、以下を考慮しておいてみるとよいのではないかと思います。

  • 実行しているOSが、Windowsか?
  • 日本語で動いているか?
それでは!

 

NUnit dnx – BlackJumboDog CoreCLR

こんにちは!前回は、xUnitどうだろうか?ということで検討していましたが、そもそもNUnitがdnxに対応してました!

NUnit 3.0.0 Release Candidate – November 1, 2015

Framework

  • The portable build now supports ASP.NET 5 and the new Core CLR.NOTE: The nunit3-console runner cannot run tests that reference the portable build. You may run such tests using NUnitLite or a platform-specific runner.

ので、移植をメインとして挑んでいくことにします!(早くデプロイしたいという気持ちが抑えられないわけではないと自分に言い聞かせる)また、注意事項が、Upgradingに書いてありました。

For example, NUnit 3.0 no longer supports ExpectedExceptionAttribute. However, preferred alternatives Assert.Throws and the ThrowsConstraint have been available for several years. If you remove the attribute from your tests and use one of the alternatives instead, you can verify that they work in your present environment and they will continue to work after conversion.

ExpectedExceptionAttributeはサポートされなくなったようです。代替として、Assert.ThrowsNUnit.Framework.Constraints.ThrowsConstraintがあるとのこと。うーん。属性によるサポートはなくなったよーみたいなことかなぁ。Exceptionの挙動は、UIスレッド(クラシックWindowsFormなApplicationException)とかAppDomain(UnhandledExceptionあたり)も絡むので、CoreCLRAppDomainの概念はそもそもないと宣言されてる。System.Windows.Formsは存在しない。どちらもないと思われる。)だとつらいとか、実は制約多いからなんかわからなくもない。VSCodeにも.Net Coreにも対応していくなら当然な流れともいえる気がします。というわけで、そのあたりも置き換えていきます! “NUnit dnx – BlackJumboDog CoreCLR” の続きを読む

xUnit dnx

こんにちは!ツイッターネタです。

BlackJumboDogにテストコードいこうぜ!ということでこんな流れになってきました。タイミングとしても、ある程度動くようにコーディングが落ち着いてきた気がしてきています。(Linux側に少し課題は残っています。)

前記事の感触から、異なるフレームワークで動くようにするということはそれぞれに動作検証やら、テストやら必要になってきそうと思っています。そんなところで、CoreCLRとしてのテストコードがほしいと思う今日この頃でした。

http://xunit.github.io/docs/getting-started-dnx.html

ほぼ、リンク先の手順通りに進めます。

といいながら、最初は、project.jsonに対して、参照の追加

  • xunit
  • xunit.runner.dnx

次に、実行するための、commandを定義します。これはkestrelとかbjdと同じでエントリポイントを指し示すようなものといえば、わかりやすいかと思っています。つまり、このプロジェクトには、MAINはいらないという意味でもあります。

 

次に、唯一のクラスを作りました。サンプル通りのものです。

ビルドすると・・・。なんと!テストエクスプローラに出てくるではないですか!!

そして、そのまま調子にのって、すべて実行!

 

動いた・・・。特に何もいれてないんですが・・・。動いた・・・。不思議だ・・・。ふつう、拡張機能とか入れるもんだと思っていたんですが。

気になって、依存関係をのぞいてみました。何やら、TestHostっていうのがあるようですね。このあたりが提供している機能に乗っかっているだけなのかもしれません。

ちょっと、これは面白くなってきた・・・!ちなみに、なぜこうなるのかは、私自身わかっていません!

それでは!!

Ubuntu上のAsyncで遅延 – BlackJumboDog CoreCLR

ずーっと気になっていたんですが、Ubuntu上でサーバーのTCPソケットをAcceptAsyncかけていたら、しばらくアクセスがない状態だと1秒程度の遅延が発生していました。そして、連続したアクセスだとこれは起きなかったんです。

元々のBjdではWhileとSleepによるポーリングを行っていたので、おそらくそんなことは起きなかっただろうと思っています。(そもそも、Begin/Endが動かなかったので、根拠はない!)

同じことが、ManualResetEventSlimeでも起きました。ある程度時間がたったときに、シグナルセット後のWait解放が1秒くらい。これ、Windowsでは起きなかったんですよね。

正直、そこまでプラットフォームに詳しい人間ではないので、なぜこうなるのか?は理解できませんでした。ただ、どうすれば?に関しては、「深い眠りにつかないようにする」っていう発想で回避しました。

https://github.com/darkcrash/bjd5/commit/a9049f8630d2e788dda19065026c415654efcd05#diff-c042d296432145429c9f5f4d27bfef99

     -            tTcp.Wait(this.Kernel.CancelToken);  
 94   +            while (true)  
 95   +            {  
 96   +                if (tTcp.Wait(2000, this.Kernel.CancelToken))  
 97   +                    break;  
 98   +                if (tTcp.Status == TaskStatus.Canceled)  
 99   +                    break;  
 100  +            }

Waitを2秒までとして、完了時はループを抜け、キャンセル時もループを抜けます。こうすることで2秒に一回このWaitが実行されます。そして、結果として遅延1秒はなくなりました。

SpinWaitの絡みとか、タイムスライスのルールとかありそうなんですが、ブラックボックスです。Darkが作るBlackなだけに・・・

これが、Kernelによるものなら、今後もこういう仕様ということになるでしょうし、.Net Coreのものであれば、改善されていくかもしれません。ので、現時点ではこのコードは、一つの回避策として整理してくださいませ!

それでは!

BlackJumboDog CoreCLR Ubuntu – Socketの置き換え APMからTAPへ

こんにちは!いきなり動いてるスクリーンショットから!!(Azure上のUbuntu14.04で動かしている様子です。)

というのも、動いてるだけでもすごいっていう気持ちを伝えたかったわけですが、今回に至るまでに行った変更点

  1. System.Net.Socketsのバージョンを他と統一し「4.1.0-beta-23516」としました。
  2. それに伴って、APMの実装は捨てられたため、TAPに書き直しました。
  3. パスの置換(\→.Netが提供するCharフィールド)を進めて動かしてみたところ、パスの置換が空回りして無限ループ!→修正済
  4. CPU利用率が起動直後で安定していても、10%以上という状況で、Thread.SleepをManualResetEventSlimに置換→アイドル中のレスポンスに1秒の遅延が発生。→検討中
  5. ConsoleTraceListenerの負荷がかかりそうなので、専用のタスクスケジューラ実装
  6. ログをそれっぽくフォーマットしました。

前回記事の、Begin/EndなどのAPM(非同期プログラミングモデル)なソケット実装がないとエラーになってました。これは、上のリンク先の通り、廃止されていくようです。このIssues(上と同じリンク) でその理由が書かれていました。Windowsに依存したようなものは排除する!っていう面白い話ですね。

ただ、これ変えてしまうと、そもそもポーリングしてるロジックとか全部作りなおしなわけで、結構時間かかってました&まだ懸念点が残ってます。行き詰っていろいろ試したのもあって、ソースの履歴が激しいことになっていてごめんなさいというところです。

また、ぜんぜん気づいていなかったのですが、Traceで出力したものは、Defaultのlistenerか何かによってだとは思いますが、しっかりとSyslogに出力されていました。(これはちょっと驚いた)

大物のWebServerが動いたので、懸念点を解消しつつデプロイ方向にシフトしていきます。

それではまた!

環境によるパスの違い – BlackJumboDog CoreCLR

前回から、Option.iniが読めてないのは見事的中しました。

https://github.com/darkcrash/bjd5/commit/789b737402a8e16b4d99147c6471eb83a426fce3?diff=unified#diff-e8a8a3be0e352480bc87c1f17ebc86bb

Windowsでは「\」をパスに利用しますが、Linuxでは「/」を利用します。ここにリテラルで「\」があったために、パスを拾えていなかったようです。これは、System.IO.Path.Combineメソッドを利用して対処しました。

でも、なんでこれで大丈夫なのだろうか?

という疑問が出てきましたので、ちょっとだけソースを追いかけてみました。

こうした環境の違いがあるために、.Net CoreのライブラリではPlatformによる違いを吸収する方法をとっているようです。

これが、Bjd(アプリ)が直接利用しているPathクラスの中身。(正確なバージョンまでは未確認。きっと多分)

System.Runtime.Extensions System/IO/Path.cs

中では「DirectorySeparatorCharAsString 」というフィールドを利用して、結合していますが、この実体はここにいません。

分割クラス(partial)となっており、

System.Runtime.Extensions  System/IO/Path.Windows.cs

System.Runtime.Extensions  System/IO/Path.Unix.cs

という風に複数定義されたものがありました。Unixでは「/」Windowsでは「\」(エスケープのため2文字なだけ)となっています。

これは、以下のプロジェクトファイルでターゲット($(TargetsUnix)、$(TargetsWindows))による切り替えが確認できます。

System.Runtime.Extensions.CoreCLR.csproj

つまり、プラットフォームごとに作られているものが違うということですね。

 

でも

2016-01-09 (1)

 

こ、今度は、BeginReceiveがないですと!!ポートが使われているよーはサービスを止めればよいとして、Windowsでは動いてるのに!!これも追いかけていこうじゃないですか!

それでは、また

 

 

Ubuntuで動いた!? BlackJumboDog CoreCLR

まずは無事に、動きました!DNX_TRACE=1から直接問題を検出できたわけではないですが、これを見ることによってどこまで動いているかの見当をつけることができたのは、StackOverflowExceptionのStackTraceを見れるのと見れないの違いくらいあるんじゃないかと思います。

2016-01-09

原因は、Consoleのサイズ取得もしくは変更をしようとしたところにありました。これは、本家Bjdにはない機能でした。GUIを捨てるときにどうしても何か見えるものをCUI上に出しておきたいと思ったのがきっかけです。Trace.Writeでトレースを出力するようにして、それをConsleに出力するためのTracelistenerを実装しています。

GitHub変更点

https://github.com/darkcrash/bjd5/commit/b42c4386866db1f681bbec13b6c20547b02e3320

Windows動かしている分には、サイズ変更できていましたが、SSH経由でそれをやると例外が発生していたようです。TryCatchを入れConsoleに出力したところメッセージが出てきましたので、取得または変更で間違いなさそうです。これもLinuxのGUI上からやったらどうなるかとかはわかりませんが、そんなことするなよって話もありつつ、やるならできない場合を考慮する必要があるようですね。

そもそも、何よ!って人に向けて

MSDN ライブラリ TraceListener クラス

これは、.NetFrameworkに昔からある機能で、Traceクラスを用いて、Writeメソッドやら、WriteLineとかで出したものを、受け取って何らかの処理をする機能を提供するための基底クラスです。ただ、.Net Core としても、Windows (ETW) があるようなので、Linuxでも動くならそっちのほうがよいでしょうね。

スクリーンショット見ると、サーバーは何も起動した形跡がないというオチが待っていました!おそらく、Option.iniを開けてとかその辺じゃあないのだろうかと思っていますが、本当に動くようになるまで戦いは続きます。

それでは、また!

 

 

 

 

 

Ubuntu dnxでTraceを出力する方法 – BlackJumboDog CoreCLR

前々日から、前日に続き

BlackJumboDogをUbuntu上で動かすために、いろいろ試行錯誤しています。どうやらUbuntuで動いていないのは本当に何か環境固有の問題ではないかと疑っています。

がしかし、何もエラーが出ずに困っていました。

そこで・・・

 

Creating a Cross-Platform Console App with DNX

https://github.com/aspnet/Home/wiki/Environment-Variables

 

ということで、環境変数を入れておけば、もっとトレース出すよ!ってことみたいです。ほかにもいろいろ変数があるようですね。

さておき、変数を設定して実行してみます。

env DNX_TRACE=1 dnx run

 

エントリポイントは再びお引越しして、bjdコマンドを定義してるので以下のように

env DNX_TRACE=1 dnx bjd

2016-01-07

何やら出てくるではありませんか!!

これをWindowsのものと比較してみます。

2016-01-07 (1)

 

アプリケーションが出すConsoleメッセージの直前は同じアセンブリを読んでるっぽいメッセージになってますね。

こうなると、PG側が悪いのではないかという疑いが出てきました・・・・!

ちなみに、UbuntuはAzureのもの使ってます。

明後日に続く!

VisualStudio がやっているdnxをLinux向けに置き換えるメモ2

前日に続き

まず、現状はうまくいっていません。ごめんなさい。

で、そもそもWindowsでもコマンドから実行させることができていない。VisualStudioで動いているからうごくもんだと思ったけど、そういうことではなかった・・・。

ので、Linuxの前にまずはWindowsのcmdからキックできることを目指すことにしました。

 

2016-01-06 (3)

ひとまず、program.csをエントリポイントとなっているアセンブリというかプロジェクトに移動させたところ動いたっぽい!いいんじゃないのいいんじゃないの!?

Ubuntuにもいっとこう!

明日に続く!

 

cheap mlb jerseys wholesale nfl jerseys cheap mlb jerseys wholesale nba jerseys