Gauche:Bugs:log19
Gauche 0.9.9以前のバグ
- Gauche の Windows 用インストーラ (0.9.9)
- ライブラリ/モジュール内で、組み込み手続きを保存して、同名の手続きを定義して中で使おうとするとするとエラー (0.9.9_rc2)
- Gauche の Windows 用インストーラ (仮) (0.9.9_rc2)
- reset/shift と call/cc の組み合わせで SEGV (0.9.8)
- Gauche の Windows 用インストーラ (仮) (0.9.8_rc1)
- tls のテストに失敗する (0.9.8_rc1)
- Invalid formal parameter (926e29f)
- MinGW-w64 (32bit) 環境で srfi-144 (flonum) のテストエラー (0.9.8_pre1)
- 32bit版の Windows で GC 8.0 の動作が不安定 (0.9.7 リリースより後の HEAD)
- GC の libatomic_ops 関連 (0.9.7 リリースより後の HEAD)
- アンダースコアの束縛 (0.9.7)
- Gauche の Windows 用インストーラ (0.9.7)
- IPv6 のデフォルト有効化について (0.9.7_pre2)
- Gauche の Windows 用インストーラ (仮) (0.9.6_rc1)
- format ~f の不具合 (0.9.6_pre4)
- Windows で gctest.exe がまれに FAIL する (0.9.6_pre2)
- MSYS2/MinGW-w64 32bit 開発環境での Gauche のビルド/テストでエラー (0.9.6_pre2)
- tls-input-port からの読み込みで ERROR: argument out of range: 1 (0.9.5, HEAD)
- Windows で HEAD のビルドエラー (0.9.5)
- TLSで接続できないWEBサーバが存在する (0.9.5)
Gauche の Windows 用インストーラ (0.9.9)
hamayama(2019/12/16 11:31:42 UTC): インストールと簡単な動作確認を実施しました。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール OK
Windows XP SP3 : 32bit 版のインストーラでインストール OK です。
(Windows XP SP3 では、gauche.net や rfc.tls 等、一部のモジュールが使用できません。
そろそろフェードアウトさせようと思います)
hamayama(2019/12/16 12:30:51 UTC): 次のバージョン番号がいくつになるのかが気になりますが。。。
個人的には、1.0 の予定に Stabilize と書いてあるのが、
逆に 0.9 ではまだまだ壊すぞという意思表示のようで、気に入っていたため、
0.9.10 でもよいのでは、と思っています。
ただ、そろそろ 1.0 にして、予定の方を 2.0 に向けて見直ししてもよいような気もします。
(Scheme の長期ビジョンが、いまいち私には見通せない感じですが。。。)
(何か、すでに Devlog の方にいろいろ書いてありました)
ライブラリ/モジュール内で、組み込み手続きを保存して、同名の手続きを定義して中で使おうとするとするとエラー (0.9.9_rc2)
(define-library (gauche-swank) (import (scheme base) (only (gauche base) keyword? keyword->string print)) (begin (define sts symbol->string) (define (symbol->string x) (cond ((keyword? x) (string-append ":" (keyword->string x))) ((symbol? x) (sts x)) (else (error "not symbol or keyword" x)))) (print (symbol->string 'abcde)) )) *** ERROR: invalid application: (#<undef> abcde) Stack Trace: _______________________________________ 0 (symbol->string 'abcde) at "(windows console standard input)":13 1 (eval expr env) at "C:\\Program Files (x86)\\Gauche\\share\\gauche-0.97\\0.9.9_rc2\\lib/ gauche/interactive.scm":269
hamayama(2019/12/04 23:10:19 UTC): r7rs-swank のソースの一部を改変したものです。0.9.8 までは動作していました。
R7RS の「5.2. インポート宣言」を見ると仕様のようですが、
古いソースではたまに見るテクニックだったように思います。
(1) 1週間前のコミット 5de965e で変わったようだが、今までの動作を可能とする余地はないのか?
あるなら 0.9.9 のリリース後に変更した方がよいのでは?
(ただ、#549 で必須の改修だったのかもしれませんが。英語がよく分からず。。。)
(2) R7RS の define-library だけでなく、Gauche の define-module でもエラーになるが、これも仕様?
(3) ライブラリ/モジュール内でなければ、動作するようですが、これも将来はエラーになる?
(4) エラーのメッセージが分かりにくいような。。。(理屈は分かりますが)
あと、R7RS の include でスタックトレースが出ない件ですが、
現状、デバッグするうまい方法があるでしょうか?
(一瞬でエラー箇所を特定されてましたが、全然分かりませんでした。include を load に変更すると別のエラーが出るし。。。)
→ これは、(import (gauche-swank)) の前に (load "gauche-swank") を書いたらスタックトレースが出ました。
- Shiro(2019/12/06 00:39:45 UTC): トップレベルで以前の束縛を保存、というのは昔のSchemeで良く使われてたテクニックですが、もともと未定義動作で、R6RSでは不可です (R7RSでは処理系依存)。 あまりに影響が大きいようなら考えますが、#549のバグの方はR7RS違反なので直さないわけにはいかず、 となると結構大規模な改修になりそうです。
- エラーがわかりにくいのは確かで、これはむしろ
(define sts symbol->string)
の時点で「symbol->stringの値は未計算だから使えないよ」というエラーにするのが良いと思っています。 初期束縛を、「スコープに入ったが未計算」を示す特殊な値にすればいいと思っているんですが、 色々検証が必要なので次リリースに回すつもりです。ただ、この件でエラーが多発してあまりに わかりにくいようだったらリリース伸ばしてエラーメッセージの改善を入れる方がいいかもしれません。 - includeでトレースが出ない件についてはアイディアがあります。こちらもちょっと大きめの 改修になるので次に回します。
- hamayama(2019/12/06 03:57:03 UTC): いまいち話がかみあわない感じですが。。。
(1) については、例えば コミット 5de965e の変更を別ブランチにして、今回のリリースから外して検討しては? という意図です。
現状の雰囲気としては、R7RS の仕様上必須なので、どうしても今回のリリースに入れたい、ということでしょうか。
(2) は、Gauche の define-module も define-library と同じ仕様。
(3) は、今はコンパイルのタイミングが異なるのでたまたま動いている。
(4) については、今後の課題。
という感じでしょうか。
- hamayama(2019/12/06 04:35:34 UTC): (3) については、Chez や Sagittarius でも、
(REPLだけでなくファイル内でも) 以下のコードが動くようなので、
使い捨てのツール等ではまだ使えるのかな?
(正規のやり方 (import (rename ...)) は、手続きの正確な所属を知らないといけないので、若干ハードルがあります);; R6RS's 'error' needs a first argument 'who'. (define error-orig error) (define (error . args) (apply error-orig 'test args))
- Shiro(2019/12/06 05:46:01 UTC): (1)この変更はバグフィクスという認識です。これまで動いていたのが 偶然であって、それが正規の動作のバグに影響している以上、できれば今回のリリースで直したいです。 但し、あまりに影響が大きければ、#529バグを直しつつ既存のコードの動作を変えないような workaroundを考えることはあり得るかもしれません (invalidなコードを温存することになるので 出来れば早いうちに変更を促したいですが。)
- (2,3) define-libraryかdefine-moduleかは関係ないです。トップレベルdefineが 個別にコンパイル+実行されるか、まとめてコンパイル+実行されるかで見え方に違いが生じ、 これは将来バッチコンパイラを導入した場合にも問題になり得ます。
- (4) さきほど、先行して作られた束縛を
#<undef>
でなく 特殊なuninitializedという値でマークするコードをpushしました。これだと例えばswankの 例なら"uninitialized variable: symbol->string" というエラーになるので 見当がつけやすくなると思います。 - R6RSでは、top-level programもしくはlibrary単位で、まず全ての束縛にダミーの値が与えられ、それから式と定義が実行されるように指定されているので、 上記のようなerrorの置き換えは動作しません (R6RS 8.2節)。 ただし、import formがなくてただ定義や式が並べてあるファイルはそもそも有効なR6RSコードでは ないので、動作は処理系依存です。
- ただ、既に同じライブラリに束縛があった場合は、2度めの
define
はset!
と同じなので、前の束縛を上の方法で保存しておくことはできます。問題となるのは他のライブラリからimportしている束縛の場合だけど、そもそも他のライブラリのerror
が見えている状態で現在のスコープでerror
を定義すること自体、R7RSでも未定義じゃないかな。
- hamayama(2019/12/06 06:50:41 UTC): うーむ。ユーザの視点からすると、R7RS はともかくとして、
Gauche はその前から存在していた訳で、仕様変更にしか見えないのですが。。。
(WiLiKi にもこんな方法があると載っていた気がします)
イメージとしては、「リテラル定数の破壊的変更」と同じで、今は動いていたとしても、
将来的に問題が生じる可能性が高い、というケースでしょうか。。。
(あれは、自分的には、納得できるものでした)
- hamayama(2019/12/06 06:50:41 UTC): R6RS の例については、実際のソースは以下になります。
https://github.com/scheme-requests-for-implementation/srfi-48/blob/25c523e1b234e646a60c7c6c7e473f422ef396a5/test/test-ChezScheme.scm
なので (import (rnrs)) は、存在していますが、これは define ごとに コンパイル+実行 しているということ?
(もっとも、規模が大きくなってライブラリ化したらNGになるので、結局よくないのでしょうが)
- Shiro(2019/12/06 08:05:40 UTC): そのChezのコードはR6RSと解釈するなら意図したように動かないはずです。R6RS 10節で定義されているように、トップレベルプログラムは意味的にはletrec*フォームに変換されて実行されます。なので該当コードは
(letrec* (... (error-orig error) (error (lambda ...)) ...) ...)
と同等であり、したがってerror-origの初期化式であるerrorは「外側のerror = (rnrs)のerror」ではなく「内側で定義されるerror」を参照してしまいます (厳密には初期化式の計算にそれより下 で束縛される変数の値を使うのは禁止なので、既にその時点でR6RSをはみ出しているんですが…)
なおGaucheのletrec*はR7RSのerrorの緩さを利用して、最適化によって順序を入れ替えたりしてるので、上のerror-origの式はそのまま通ります。最適化によってerror-orig自体消えちゃうので。 - ただ、規格はともかくとして既に以前の振る舞いに依存したコードが大量にあるなら 少なくとも移行期間を設けて徐々に移行すること自体はやぶさかではありません。 今回変えちゃったのは、自分的には「未定義動作使ってる人そんなにおらんだろう」という目論見が あったからで、たくさん使われてるなら話は別です。 なお、「トップレベルフォームが一度にコンパイルされること」が問題なので、 現在のGaucheであってもトップレベルで上のChezのような書き方をしている場合は通ります。 swankで問題が出たのは、includeで読まれるファイルは実質的にbeginの中に入って一度に コンパイルされるからです。
- Shiro(2019/12/06 08:46:05 UTC): Scm_FidnBindingに新たなオプションをつけて モジュール処理時(Scm_AliasBinding)と通常のルックアップでuninitializedの 扱いを変える、というふうにしたら#529をfixしつつこれまでの振る舞いはキープできるかも。 そんでwarningから禁止に徐々に移行してけば。
- hamayama(2019/12/06 09:12:40 UTC): うーん。大量にかどうかは、何とも。。。
エラーメッセージも改善されたし、将来を考えると、(先送りするより) これでよいのかも。
現状の理解としては、ライブラリ内はまとめてコンパイルするようになっていて、
error は、uninitialized に束縛される。
そうすると、#549 のように (import (only ...)) を使った場合にも、
error がすでに存在するので、正しく動く。
ただ、実行時には、error を組み込みの error として認識させることは、できなくなった。
これは、error がすでに uninitialized に束縛済みだからである、と。
理由は分かった気がします。。。
- Shiro(2019/12/06 10:41:54 UTC): R5RSまでは公式のモジュールシステムが無かったので、 同じ名前空間内の再定義というセマンティクスで上のerrorのようなコードは良く書かれていました。 もしかするとSLIBにもまだそういうのがあるかも。 昔のコードをそのまま読み込んで使いたい、という用途があり得ることを考えると、 何らかの方法で切り替えらえることは望ましいですね。 古いコードなら逆に#529問題を考える必要はないので、コンパイル時フラグで切り替えちゃっていいかも。それなら多分すぐできる。
- hamayama(2019/12/06 11:41:52 UTC): 開発側の視点もだんだん分かってきました。
間に「実行」を挟まないと、(import (only ...)) が機能しないのは、確かにまずいですね。
2007年の R6RS の時点で、すでにその辺りの事がまとめられていて、
R7RS の記述も、R6RS を知っている人であれば、理解できると。。。
そう考えると、今回の修正は、遅すぎるくらいかもしれませんね。
- hamayama(2019/12/06 12:06:26 UTC): Chez の例ですが、--program オプションを付けて実行したところ、
ちゃんと以下のエラーになりました。
オプションを付けないと、REPL のように逐次読み込みで実行するのではないかと。Exception: multiple definitions for error in body (top-level-program #<annotatio n test-ChezScheme.scm[46:61] (import (...))> #<annotation test-ChezScheme.scm[73 :1257] (define-syntax cond-expand (...))> #<annotation test-ChezScheme.scm[1307: 1332] (define error-orig error)> #<annotation test-ChezScheme.scm[1333:1388] (de fine (...) (...))> #<annotation test-ChezScheme.scm[1390:1499] (define (...) (.. .))> ...) near line 5, char 1 of test-ChezScheme.scm
- hamayama(2019/12/11 14:26:44 UTC): 今回の件とは異なりますが、
R6RS および R7RS の仕様について、少し気になったことがあります。
それは、「今後、標準ライブラリの手続きが増えるたびに、
ユーザのプログラムが動作しなくなる可能性がある」という点です。
例えば、hoge という手続きをユーザが自分のプログラム内で定義していた場合、
(scheme base) に後から hoge という手続きが追加されてしまうと、
ユーザのプログラムは、エラーもしくは未定義動作になってしまいます。
これでは、安心してプログラムを作成/運用することができないと思うのですが。。。
この場合、(現状の Gauche のように) shadowing を優先すべきではないでしょうか。
- Shiro(2019/12/11 21:55:16 UTC): R6RS/R7RSの標準ライブラリ手続きは増えません。増える時はR8RSのタイミングか、R7RS-largeのように別ライブラリとしての追加になります。
ただ、一般のライブラリの運用まで考えれば名前の追加による衝突は考えられます。 R6RSのライブラリバージョニングはそのために導入された仕様なんですが、 常にソース上でライブラリのバージョンをpinするってのはいまいち使い勝手が悪いんですよね。
R7RSは緩くしたので、Gaucheのようなシャドウイングも許されることになりました。
- hamayama(2019/12/12 03:39:00 UTC): なるほど。情報ありがとうございます。
よく考えると、一般のライブラリ A と B を この順に import していて、
A に所属する手続き aaa を使用していた場合に、後から B にも aaa が追加された場合、
結局おかしくなるので、shadowing で全て解決するものでもないか。。。
(この場合、むしろエラーになった方がよい? 検出ツールとか需要があるかも)
バージョンを固定する方式だと、ライブラリのバグ Fix 時には全バージョンを
改修しないといけなくなるので、それはそれで大変そうですね。
結局、(prefix を使う等) なるべくバッティングしないような名前を使うのが、現実的なのかも。
- Shiro(2019/12/12 04:09:07 UTC): goはimportは原則全部prefixつきですがたくさんのライブラリが非同期にアップデートされる環境では良い解だと思います。
- hamayama(2019/12/12 11:48:07 UTC): 環境変数 GAUCHE_LEGACY_DEFINE の動作を確認しました。よい感じです。
テストしていて気が付いたのですが、Gauche のモジュール内であっても、
select-module を使用してインデントをなくしていた場合には、
逐次コンパイルになって、今回の件はエラーにならないのですね。
(もちろん include したり begin で囲ったりすればエラーになります)
これは、あまり顕在化しないかも。。。
個人的には、R7RS における未定義状態かどうかのチェッカーを作ってみようと思います。
ただ、Gauche の本体には、あまり R7RS 方式を推奨してほしくない気がします。
行きつくところまでいくと、ライブラリの API はバージョン固定で、
ライブラリ名の最後に数字を付加して区別しましょうとか、なると思うのですけど、
それはうれしくない気がします。
(今回の変更が必要な範囲であるということは、理解しています。その先の話です)
- hamayama(2019/12/13 14:14:00 UTC): import されたシンボルの重複チェックを行うモジュールを作成してみました。
https://github.com/Hamayama/dupsyms
素の状態でもけっこう重複があるようです。
- Shiro(2019/12/14 08:29:27 UTC): define, import, lambda, read-eval-print-loopはそれぞれ定義が違うのをわざとシャドウしてるので想定内ですが、cxrは想定外です。マクロで自動生成してるのが重複して走ってる?
- Shiro(2019/12/15 09:43:12 UTC): ああわかった。cxrはインライン可能にするために、一旦gaucheモジュールでdefine-inline定義してからschemeモジュールに束縛を持ち込んでるんだ。これはschemeモジュールで直接inline定義できるようにすれば解決するけど、どうすっかな。
Gauche の Windows 用インストーラ (仮) (0.9.9_rc2)
hamayama(2019/12/03 06:26:46 UTC): インストールと簡単な動作確認を実施しました。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール OK
Windows XP SP3 : 32bit 版のインストーラでインストール OK です。
(llibwinpthread-1.dll のドキュメントも確認できました。対応ありがとうございます)
(XP で gauche.net をロードすると、inet_ntop がないというエラーが出ますが、
さすがにもう仕方ないかなと思います。。。)
- Shiro(2019/12/04 11:18:42 UTC): Windowsのどのバージョンから対象にしてたかもう忘れちゃったですが、 XPはとっくにサポート切れですしいいでしょう
reset/shift と call/cc の組み合わせで SEGV (0.9.8)
hamayama(2019/09/07 08:01:16 UTC): どうも自分には直せないみたいなので、まずは挙げておきます。
(use gauche.partcont) (define k1 #f) (define k2 #f) (define (f1) (call/cc (^[k] (set! k1 k))) (shift k (set! k2 k)) (display "[f01]")) (define (f2) (display "[f02]")) (reset (f1) (f2)) (reset (k1))
発生条件があります。
(1) (reset (f1)) として、(f1) を末尾呼び出しにしたとき ((f2) を消したとき) は、
SEGV にはならず、以下のエラーが出る。
「*** ERROR: attempt to return from a ghost continuation.」 ... (A)
(2) (shift k (set! k2 k)) を消すと、SEGV にはならず、エラー (A) が出る。
(3) (k1) を reset で囲わなければ、SEGV にはならず、REPL が終了する。
(4) (reset (reset (f1) (f2))) のように reset でもう一段囲うと、SEGV にはならない。
→ (k1) の reset より段数が多ければ大丈夫なよう。。。
(1)-(4) は、仕様の範囲内かと思うのですが、上の例ではそれらのチェックをすり抜けている感じです。
hamayama(2019/09/14 05:21:55 UTC): 以下で対策を行いました。
https://github.com/shirok/Gauche/pull/518
Gauche の Windows 用インストーラ (仮) (0.9.8_rc1)
hamayama(2019/06/09 03:09:07 UTC): インストールと簡単な動作確認を実施しました。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール OK
Windows XP SP3 : 32bit 版のインストーラでインストール OK です。
- Shiro(2019/06/09 03:53:05 UTC): いつもありがとうございます。
- hamayama(2019/06/17 14:26:09 UTC): 0.9.8 リリースおめでとうございます。
(上と同じ環境にインストーラでインストール確認し OK です)
tls のテストに失敗する (0.9.8_rc1)
hamayama(2019/06/07 11:36:54 UTC): 以下の件です。
https://twitter.com/SaitoAtsushi/status/1136905446285930497
https://gist.github.com/SaitoAtsushi/46f53e03331c0723e057753b6850ff5d
どうもこちらで再現しないため、いくつか確認したい点があります。
(1) openssl.exe をサーバモードで起動できるか
cd /c/work/Gauche/ext/tls/axTLS/ssl/test openssl s_server -cipher DEFAULT@SECLEVEL=1 -accept 19002 -quiet -cert axTLS.x509_1024.pem -key axTLS.key_1024.pem
のようにして、openssl.exe をサーバモードで起動します。
別の画面を開いて、
netstat -a -n | grep 19002
のようにして、サーバ が ポート 19002 で LISTEN できているかを確認します。
(例えば、ウィルス対策ソフトがブロックしている等があるかもしれない。。。)
(2) openssl.exe の種類
where openssl で、どの openssl.exe が使用されているかを確認します。
MinGW の openssl.exe については、
https://github.com/shirok/Gauche/pull/468 で、
MinGW の openssl.exe が固まらないように、winpty をかませるようにしました。
この対策が悪さをしている可能性もあります。
例えば、MinGW の openssl.exe をリネームして使えないようにして、
MSYS2 の openssl.exe を使うようにしたら、成功するでしょうか。
齊藤 (2019/06/08 00:58:24 UTC):
- (1) については LISTEN できていることを確認できました。
MinGW の openssl.exe と Msys の openssl.exe との両方で確認できました。 - (2) については、 MinGW の openssl.exe をリネームして封じると (Msys の openssl.exe が使われるようにすると) テストは成功しました。
hamayama(2019/06/08 01:13:28 UTC): 回答ありがとうございます。
これは、where openssl で openssl.exe のリストを取得して、
Msys のものを優先的に起動する (kick_openssl.sh 内でフルパスで指定する)
方がよさそうですね。。。ちょっと検討してみます。
hamayama(2019/06/08 04:36:31 UTC): うーむ、Msys のものを使うようにしたら、逆にエラーが出るようになってしまった。。。
( could not start socket on 19002 )
hamayama(2019/06/08 04:50:42 UTC): ssltest.c の以下のところで fd < 0 をチェックしてエラーにしているのですが、
https://github.com/shirok/Gauche/blob/a085214948c1f9b737a37a1a503e8170b2d0bd28/ext/tls/axTLS/ssl/test/ssltest.c#L1678
どうも winsock の SOCKET は unsigned で、INVALID_SOCKET 以外の値は正常値なもよう。。。
https://docs.microsoft.com/en-us/windows/desktop/winsock/socket-data-type-2
hamayama(2019/06/09 03:09:07 UTC): 以下で修正してみました(発生の頻度の違いがちょっと気になりますが。。。)。
https://github.com/shirok/Gauche/pull/479
齊藤 (2019/06/09 15:30:49 UTC): 私の手元ではその変更を適用して (コンパイルは ./DIST gen
からやり直してます) も rfc.tls
は failed になってしまいました。
ところで気になるのは、 ssltest.log に残される invalid digest とか Unsupported digest とかいった形のエラーになって現れるのはどういう理屈か判明しているのでしょうか?
パイプやソケットの接続の都合で固まってしまったり入出力のエラーになるというのなら話はわかるのですが、ハッシュが違うことを表す (んですよね?) メッセージを私は理解できていません。
Shiro(2019/06/09 18:42:14 UTC): このメッセージなら想定内です。これは無効な証明書が含まれたバンドルを読むテストで、無効な証明書に出会うとこのメッセージが出力されますが、有効な証明書がひとつあればokというテストなので。
invalid digest: 2a 86 48 ce 38 04 03 Error: Invalid X509 ASN.1 file (Unsupported digest) invalid digest: 2a 86 48 ce 3d 04 03 03 Error: Invalid X509 ASN.1 file (Unsupported digest) All Certificate tests passed
hamayama(2019/06/09 20:26:08 UTC): 参考用に成功時の ssltest.log を以下のページに生成してみました (AppVeyor) 。
https://ci.appveyor.com/project/Hamayama/gauche/builds/25153825/job/bkv3n51i42vv0d2a/artifacts
(1) エラーの内容は変わらず ( could not start socket on 19002 ) でしょうか。
(2) 念のため、以下のファイルの状況 (内容、日付が更新されているか) を確認してほしい。
ext/tls/axTLS/ssl/test/ssltest.c (ソース)
ext/tls/axTLS/ssl/test/ssltest.mod.c (ソースを自動変換したもの)
ext/tls/axTLS/ssl/test/ssltest.mod.o (オブジェクト)
ext/tls/axTLS/ssl/ssltest.exe (実行ファイル)
ext/tls/ssltest.log (ログ)
(3) Msys の openssl.exe だと、相変わらず成功するでしょうか。
(全テスト実行しなくても cd ext/tls → make check で確認できると思います)
(4) winpty --version でバージョンが知りたい (こちらは 0.4.3)。
齊藤(2019/06/10 01:52:44 UTC):
- エラーの内容は
could not start socket on 19002
です。 - 各種ファイルは更新されています。
- Msys の
openssl.exe
であれば成功します。 - winpty はインストールしていませんでした。
つまらないことにお手数をおかけしてすいません。
winpty
が必要というのはドキュメントに書いてあるのを見落としていました。
ただ、エラーメッセージを工夫する余地はあるかもしれません。
Shiro(2019/06/10 03:59:37 UTC): winptyを入れたら通りました? それならconfigureで チェックして無かったらメッセージ出してテストスキップでいいかな?
齊藤(2019/06/10 04:53:14 UTC): はい。 winpty
を入れたら passed
になりました。
hamayama(2019/06/17 14:26:09 UTC): #480 #481 #482 で、winpty が見付からないときはメッセージを出すようにしました。
Invalid formal parameter (926e29f)
このようなコードを実行するとエラーになります。
(import (scheme base) (scheme write)) (define-syntax apply-values (syntax-rules () ((_ f e) (call-with-values (lambda() e) (lambda lst (apply f lst)))))) (display (apply-values list (values 1 2 3)))
エラーの内容は
*** ERROR: Invalid formal parameter: #<identifier r7rs.user#lst.31b4430> While compiling "./test.scm" at line 10: (display (apply-values list (values 1 2 3))) While loading "./test.scm" at line 10 Stack Trace: _______________________________________
です。
import に (gauche base) を追加する、またはマクロを使わない形で
(display (call-with-values (lambda() (values 1 2 3)) (lambda lst (apply list lst))))
とすると問題なく動作するようです。
- hamayama(2019/04/30 12:13:44 UTC): 少し調べてみました。
エラー場所: src/compile-1.scm (define-pass1-syntax (lambda form cenv) :null ;RnRS lambda にある (error "Invalid formal parameter:" formals)
<関係がありそうなコミット>
2019-2-24 Make RnRS lambda accept keywords as arguments #451
( https://github.com/shirok/Gauche/commit/6fd80a0d88988e7447286dc14305d75a615d6951 )
2019-2-25 Editorial changes, error checking in vanilla lambda
( https://github.com/shirok/Gauche/commit/068914f9babc255317d44fae334889090725307e )
最近変更されたところのようで、Gauche 0.9.7 までは問題がないようです。
暫定の対策としては、src/compile-1.scm の
(define-pass1-syntax (lambda form cenv) :null ;RnRS lambda
のところにある (symbol? xs) を (variable? xs) にすれば回避できるようです。
(variable? は、symbol? と identifier? の or です)
(正式には、見てもらった方がよいと思いますが。。。) - Shiro(2019/05/06 01:21:34 UTC): Hamayamaさん、そのfixで正解です。push済。
MinGW-w64 (32bit) 環境で srfi-144 (flonum) のテストエラー (0.9.8_pre1)
hamayama(2019/04/16 10:23:14 UTC): テスト結果は以下になります。64bit 環境では発生しません。
https://ci.appveyor.com/project/Hamayama/gauche/builds/23869905/job/cr3gkpm8ua5yh7t9#L1808
Testing extension srfi modules ... failed. discrepancies found. Errors are: test (flsign-bit negzero): expects 1 => got 512 test (flsign-bit (flonum -2)): expects 1 => got 512 test (flsign-bit neginf): expects 1 => got 512 test (flnormalized? fl-least): expects #f => got #t test (fldenormalized? fl-least): expects #t => got #f
最初の3件については、C の signbit が負のときに非0を返すとのことなので、直せそうです。
後の2件については、MinGW-w64 (32bit) 環境 の fpclassify のバグのようで、
ちょっとよい対応方法が思いつきませんでした。
(fxam と fstsw という 8087 の 80bit用の命令が使われていて、
小さい数が FP_NORMAL と判定されてしまうようです。。。)
<参考URL>
https://stackoverflow.com/questions/31714128/why-is-isnormal-saying-a-value-is-normal-when-it-isnt/31715338#answer-31715338
https://sourceforge.net/p/mingw-w64/bugs/367/
hamayama(2019/04/17 10:05:52 UTC): 本件は修正済みです。
32bit版の Windows で GC 8.0 の動作が不安定 (0.9.7 リリースより後の HEAD)
hamayama(2019/01/12 09:37:35 UTC): 現象としては、ビルド中や make check 中に、
Fatal error in GC「Unexpected mark stack overflow」というメッセージが出て落ちます。
少し調べた感じでは、libatomic_ops の使用有無や configure の設定とは無関係で、
基本的なところで何か変わっている印象です。
ソースもずいぶん変わっていて、ちょっとすぐには切り分けができなさそうです。
暫定対策としては、GC を gc-7.6.10 + libatomic_ops-7.6.8 に差し替えれば、動作します。
(gc フォルダを入れ替えて、gc フォルダの中に libatomic_ops フォルダを入れる)
ただし、差し替える場合、現状の Gauche HEAD では、Gauche 側も 一部修正が必要になります。
(Gauche側の修正に関しては、プルリクエスト #422 を出しました)
hamayama(2019/01/14 08:58:17 UTC): ある程度調べて、GC側にあげておきました。
https://github.com/ivmai/bdwgc/issues/260
現状、まだ切り分けが不十分です。。。
hamayama(2019/01/23 11:48:24 UTC): 以下で修正されました。
https://github.com/shirok/Gauche/pull/438
ただ、テスト中に別の問題が見つかっていて、そちらは未解決です。
https://github.com/ivmai/bdwgc/issues/262
(Gauche の動作とは関係ないかもしれません)
hamayama(2019/02/09 06:06:18 UTC): 以下で対策されました。
https://github.com/shirok/Gauche/pull/445
GC の libatomic_ops 関連 (0.9.7 リリースより後の HEAD)
hamayama(2019/01/07 06:20:57 UTC): 下記URLの件ですが、以前 GC を調査したときに、
次期バージョンでは (Cコンパイラが対応していれば) libatomic_ops なしで
GC のビルドが可能になるという情報がありました。
https://twitter.com/dico_leque/status/1081896341754630144
ログを見ると、Gauche 側の configure では、
checking which libatomic_ops to use... internal
となっており、GC 側では、
checking which libatomic_ops to use... none
となっているので、この不一致が関係しているのではないでしょうか。
(自分の環境ではビルドはできていますが。。。)
例えば、tools/gc-configure.gnu-gauche.in に
--with-libatomic-ops=no \
を追加して、GC 内の libatomic_ops のみを使用するようにしたら、
とりあえずはビルドできるかもしれません (none と no とで意味が変わるようです)。
- Shiro(2019/01/07 06:34:46 UTC): あれ、https://github.com/shirok/Gauche/commit/622c7591985912139624683395493045ee5ab6f3 で直したと思ったんだけどまだだめかな。noneになるとlibatomic_ops以下にオブジェクトが作られないのでそれへの対応。Dockerで作ったDebian環境ではlibatomic_ops=noneだけどこのコミットでビルドできてます。
- hamayama(2019/01/07 12:28:32 UTC): 上記 URL の travis-ci のログによると、
ar -rc libatomic_ops_pic.a でエラーになっています。
確かに libatomic_ops_pic_OBJECTS は空になっていますが、
その空から libatomic_ops_pic_LIBRARY を作ろうとするようです。
- Shiro(2019/01/07 17:35:54 UTC): ああ、確かに。Debian/Docker環境のar (ar 2.28 from GNU binutils) はアーカイブすべきファイルをひとつも指定しなくてもエラーにならない(空のアーカイブファイルが作られる)から通っていた模様。
- Shiro(2019/01/10 04:14:58 UTC): 根本的に直そうとしたらちょいと厄介なことが判明。齟齬の原因はGaucheのconfigureとgcのconfigureでlibatomic_opsの検出方法がずれたことなんだけど、compiler intrinsicの検出のためにlibatomic_opsの検出方法がが複雑化していて、同じことをGaucheで繰り替えしたくはない。できればgcでlibatomic_opsの検出をやった結果をGaucheの方でも流用できたら、と思うんだけど、autoconfの仕組み上かなりアクロバティックなことをやらないとできなさそう。
- hamayama(2019/01/10 08:40:37 UTC): 別件になるのですが、どうも 32bit版の Windows で、
GC が不安定になるという問題があるようです。詳細は別途報告しますが、
しばらくは、GC v7.6 系と切り換えができるとうれしいかも。。。
アンダースコアの束縛 (0.9.7)
齊藤(2018/12/28 08:35:14 UTC): R7RS によれば、アンダースコア (_) は (scheme base) や (scheme r5rs) で束縛されている識別子ということになっていますが、現在の Gauche ではそうなっていないようです。
- Shiro(2018/12/29 23:44:47 UTC): ダミーの
#<syntax>
に束縛して(scheme base)
からexportしました。R7RS Appendix Aを見る限り、これらは(scheme r5rs)
からはexportされないようですが… - 齊藤(2018/12/30 15:46:57 UTC): R7RS の Errata の 22 番目で
(scheme r5rs)
からエクスポートすべきである (should) となっています。
must ではありませんが、特別に避ける理由も無さそうに思いました。 - Shiro: あっそういえばそんな議論がありました。忘れてました。 確か、R5RSではsytnax-rulesのリテラル識別子マッチの定義が緩くて 未束縛でもいけたのが、真面目に使い込もうとするとやっぱり起源がはっきりしてないと 扱い辛いよねってなったんでしたっけ。exportしときます。
Gauche の Windows 用インストーラ (0.9.7)
hamayama(2018/12/22 10:16:14 UTC): 0.9.7 リリースおめでとうございます。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール OK
Windows XP SP3 : 32bit 版のインストーラでインストール OK です。
(バグはありませんが、一応記録として残しておきます)
IPv6 のデフォルト有効化について (0.9.7_pre2)
hamayama(2018/12/03 12:54:08 UTC): コミット 64e57dc (2018-12-3) で、IPv6 のデフォルト有効が明記されましたが、
現状、src/mingw-dist.sh では、configure のオプションに --enable-ipv6=no を指定しています。
これは、IPv6 を有効にしたバイナリを、IPv6 が無効に設定されている PC で実行すると、
(make-server-socket 'inet 8080) でエラーになったためだと思います。
(家の Windows PC では、IPv6 の ON/OFF を、ドライバの設定画面で選択できます)
本件は、対策方法がありますが、確か、何か気になる点がありました。
(だいぶ忘れかけていますが。。。)
まず、確か、(make-server-socket (make <sockaddr-in> :host :any :port 8080)) のように
IPv4 を指定すると、エラーは出なくなります。
だた、それだと IPv4 用のプログラムになります。
また、以下のように ipv6-capable を上書きする方法もあったように思いますが、
これは、たまたまチェックに失敗したら、以後は IPv4 になります。
(with-module gauche.net (set! ipv6-capable (and (global-variable-bound? 'gauche.net 'sys-getaddrinfo) (guard (ex ((<system-error> ex) #f)) (socket-close (make-socket AF_INET6 SOCK_STREAM)) #t))))
結局、Windows のインストーラでは、トラブルの元になると考え、
--enable-ipv6=no に設定したように思います。
(必要なユーザは --enable-ipv6=yes で個別にビルドしてもらうということで)
今考えると、ビルドは --enable-ipv6=yes で行い、
何らかの方法で、[IPv4 のみ] / [IPv6 のみ] / [IPv4 と IPv6 の両方に対応] のような
選択を可能にして、Windows の場合は デフォルト設定を [IPv4 のみ] にしておくのが
一案かなとも思いますが。。。
- Shiro(2018/12/05 11:07:37 UTC):
make-server-socket-inet
でv4とv6のsockaddrを 作ってつなぎにゆくあたりを、それぞれguardするのがいいかなあ。
- hamayama(2018/12/06 11:29:48 UTC): どうも記憶があいまいなため、後でもう一度調べてみます。
hamayama(2018/12/07 13:18:40 UTC): すいません。再度確認したところ、特にエラーとなることはありませんでした。
確認した環境は、以下の4つです。
(1) Windows 8.1 (64bit) で IPv6 をドライバの設定画面で有効にした場合
(2) Windows 8.1 (64bit) で IPv6 をドライバの設定画面で無効にした場合
(3) Windows 8.1 (64bit) で (2) に加えて、レジストリで IPv6 を無効にした場合 (DisabledComponents: 0xff)
( https://support.microsoft.com/en-us/help/929852/guidance-for-configuring-ipv6-in-windows-for-advanced-users )
(4) Windows XP SP3 (IPv4のみ)
以下のページによると、Windows Vista 以降では、IPv6 を無効に設定しても、
Loopback インターフェース だけは無効化できないようです。
https://blogs.msdn.microsoft.com/shintak/2015/01/12/ipv6/
このため、(make-server-socket 'inet 8080) で [::]:8080 がオープンできないというケースはありませんでした。
ただ、ドライバでは IPv6 が無効になっているため、外部から接続することはできませんが。。。
Windows XP SP3 については、getaddrinfo が IPv4 のアドレスだけを返すため、
0.0.0.0:8080 が正常にオープンされました。
以下のページによると、Windows XP では IPv6 がなくても getaddrinfo が使えるようです。
http://www.geekpage.jp/programming/winsock/getaddrinfo.php
結局、src/mingw-dist.sh でも --enable-ipv6=yes でよさそうです。
(2) (3) のケースで、IPv4 のアドレスを優先する方法があるとうれしいかとも思いますが。。。
((3) のURLにある「Prefer IPv4 over IPv6 (DisabledComponents: 0x20)」の設定をしても、
getaddrinfo の返す順番は変わらないようでした)
- Shiro(2018/12/10 03:54:14 UTC): 検証ありがとうございます。IPv6を設定でオフにしていた場合、
プログラムとしてはエラーを出さないが、サーバソケットがv6優先でbindされてしまうため、
外からつなげなくなる、という理解で良いでしょうか。
おそらく今後書くサーバについてはmake-server-sockets
を使って複数プロトコルで bindするのを推奨すべきだと思うんですが、今までv4がbindされることをあてにしてた プログラムが動かなくなるのはいまいちですね。経過措置としてwindowsの場合だけ getaddrinfoの結果をv4優先でソートしようかな。
- hamayama(2018/12/11 13:17:53 UTC): そうなります。(2) (3) のケースについて、
エラーにはならず、外部からは接続できません。
(同一 PC 内であれば [::1]:8080 で接続できました)
(念のため、外部から IPv4 のアドレスも指定してみましたが、つながることはありませんでした)
hamayama(2018/12/11 13:17:53 UTC): とりあえず試験的に以下のようにしてみたところ、
IPv4 でオープンされて外部から接続できることが確認できました。
(use gauche.net) (with-module gauche.net (define (make-sockaddrs host port :optional (proto 'tcp)) (let* ([socktype (case proto [(tcp) SOCK_STREAM] [(udp) SOCK_DGRAM] [else (error "unsupported protocol:" proto)])] [port (x->string port)] [hints (make-sys-addrinfo :flags AI_PASSIVE :socktype socktype)]) (map (cut slot-ref <> 'addr) (sort (sys-getaddrinfo host port hints) string<? (lambda (ai) (x->string (~ ai 'family)))))))) (make-server-socket 'inet 8080)
- Shiro(2018/12/12 13:15:01 UTC): 泥臭いですが、これまでとの互換性を重視して アドホックにWindowsだけv4優先、としてしまってもいいかも。 インストーラから使っていた場合もともとv6が使えなかったわけで、その挙動は保たれます。 後で必要になったらランタイムに選択可能にするAPIつけられますし。
- hamayama(2018/12/16 05:42:08 UTC): 以下で対応を行いました。
https://github.com/shirok/Gauche/pull/403
(src/mingw-dist.sh で --enable-ipv6=yes を指定。
また、Windows のときは、make-sockaddrs が IPv4 アドレス を優先して返す)
Gauche の Windows 用インストーラ (仮) (0.9.6_rc1)
hamayama(2018/07/02 16:43:17 UTC): インストールを実施しました。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール
Windows XP SP3 : 32bit 版のインストーラでインストール
以下は気が付いた点です。
(1)64bit版について、mbedTLS を使おうとすると、libgcc_s_seh-1.dll がないというエラー
(依存関係をツールでみると、libmbedcrypto.dll が libgcc_s_seh-1.dll に依存しているようでした)
gosh> (use rfc.tls) gosh> (default-tls-class <mbed-tls>) *** ERROR: failed to link C:\Program Files (x86)\Gauche\lib\gauche-0.9\0.9.6_rc1 \x86_64-w64-mingw32/rfc--tls--mbed.dll dynamically: error code 126 While loading "C:\\Program Files (x86)\\Gauche\\share\\gauche-0.9\\0.9.6_rc1 \\lib/rfc/tls/mbed.scm" at line 39 Stack Trace: _______________________________________ 0 <mbed-tls> [unknown location] 1 (eval expr env) at "C:\\Program Files (x86)\\Gauche\\share\\gauche-0.9\\0.9.6_rc1\\lib/g auche/interactive.scm":267
32bit版の方は問題ありませんでした。
使っている mbedTLS は MSYS2 の pacman で入るものでしょうか?
- Shiro: (2018/07/02 22:01:15 UTC): mbedTLSはpacmanで入れたやつです。そうかーlibgccのdllに 依存しちゃうのかー。本体を-static-libgccでリンクしてもmbedのdllには影響与えないですよねえ。 dllを同梱するとGPLになっちゃうからなあ。どうしようかなあ。 mbedを-static-libgccでリビルドするという手はあるかもしれないが面倒だなあ。
- Shiro:(2018/07/03 01:09:18 UTC): とりあえず0.9.6のバイナリインストーラはmbedTLSなしで出して、 使いたい人はmingw/msys2でビルドしてもらう、で行こうと思います。 mingw/msys2があれば、pacmanでmbedtls入れてビルドするだけなので。
- hamayama(2018/07/04 08:23:02 UTC): 0.9.6 リリースおめでとうございます。
Windows 8.1 (64bit) : 64bit 版と 32bit 版のインストーラでインストール OK
Windows XP SP3 : 32bit 版のインストーラでインストール OK です。
mbedTLS の件は、後でこちらでも少し調べてみます。
(PKGBUILD ファイルで対応する方法がありそうです)
- hamayama(2018/07/06 14:24:18 UTC): libgcc_s_seh-1.dll に依存しない mbedTLS のパッケージを、
生成するツールを作りました。
https://github.com/Hamayama/Gauche-static-mbedtls-mg
Mingw のパッケージスクリプトを取得して、PKGBUILD ファイルにスタティックリンクのオプションを追加し、
ビルドしてパッケージを生成するところまで自動で行います。
また、Gauche の mingw-dist.sh を書き換えて、mbedTLS のサポートを有効にするツールも入れておきました。
format ~f の不具合 (0.9.6_pre4)
hamayama(2017/10/22 19:20:43 UTC): 以下のケースが見つかりました。
(format "~,1f" 123.95) -> "123.:" (format "~,2f" 999.995) -> "999.9:" (format "~,10000f" 1) -> SEGV
テストに使用したファイルは以下になります。
https://gist.github.com/Hamayama/d99c25902983670ffc0a55c1cfc320e1
- Shiro(2017/10/23 05:19:24 UTC): ':' てどっから来たんだ、と思ったら'9'の次か! 繰り上がりの伝搬が止まってるからっすね。最後のやつはバッファオーバーフローっぽいからやばい。まはろです。
- Shiro(2017/10/26 20:45:09 UTC): fixをpushしました。
- hamayama(2017/10/27 08:40:45 UTC): 修正されていることを確認できました。
hamayama(2017/10/27 19:41:24 UTC): どうも、よく分からなくなってしまったのですが。。。
format ~f の digits とは、固定小数点での指定なのか、正規化後の小数点での指定なのか。。。
(format "~1,2f" 1.003) ; -> 1.00 (これは正しい) (format "~1,2f" 0.003) ; -> 0.003 (これは 0.00 になるべき?) (format "~1,2f" 0.0003) ; -> 3.00e-4 (これは正しい?) (format "~1,2f" 1) ; -> 1.00 (これは正しい) (format "~1,2f" 10) ; -> 10.00 (これは正しい?) (format "~1,2f" 1000000000) ; -> 1.00e9 (これは正しい?)
hamayama(2017/10/30 01:28:33 UTC): 大きな浮動小数点数を固定小数点で表示しても意味がないので、
これはこれでよい仕様な気がしてきました。
あとは、指数表示に切り替わる桁数が、カスタマイズできるとうれしいと思います。
あと、上記の (format "~1,2f" 0.003) -> 0.003 だけは、バグのような気がします。
- Shiro(2017/10/30 13:40:32 UTC): ども。digitsは正規化後の小数点以下の桁数です。0.003以外は想定どおりです。
指数表示への切り替えの閾値は、低レベルルーチンでは指定可能になってるんですが、上位にどう見せるか思案中です。Common Lispだと~f
は常に指数表示無し、~e
は常に指数表示、~g
は絶対値によって切り替え、となるんですが、切り替えの閾値は表示される数値の幅によるので自由な指定はできないですね。
hamayama(2017/11/09 10:39:27 UTC): (format "~1,2f" 0.003) の件は修正済みです。
Windows で gctest.exe がまれに FAIL する (0.9.6_pre2)
hamayama(2017/06/05 13:50:34 UTC): make check でまれに gctest.exe が FAIL します。
(Gauche 自体は正常に動作しているようですが)
それで、GCの方に報告してみました。
https://github.com/ivmai/bdwgc/issues/166
最近、libatomic_ops が v7.6.0 に更新されましたが、v7.4.4 に戻してみても現象は同じでした。
hamayama(2017/06/16 10:28:07 UTC): 切り分けの結果、gctest.exe 内の
GC_malloc_explicitly_typed という API のテストで SEGV が発生すると分かりました。
この API は Gauche では未使用であるため、Gauche の本体の実行には影響がないと思います。
(gctest.exe で、このテストだけスキップすることは現状できないようです。。。)
また、開発最新版の GC v7.7.0 では、
gctest.exe に GC_MALLOC_WORDS という API のテストも追加されており、
そこでも SEGV が発生するようでした。将来取り込まれるのであれば、要注意かと。。。
(ただし、以前発生していた GCJサポートのテストで SEGV が発生する件については、
修正されているようでした)
hamayama(2017/06/21 07:03:09 UTC): その後、発生行の切り分けができて、GC v7.7.0 では直りました。
Issue #166: MinGW: gctest.exe fails infrequently in typed alloc
https://github.com/ivmai/bdwgc/issues/166
また、GC_MALLOC_WORDS の不具合についても、GC v7.7.0 では直りました。
Issue #167: MinGW: gctest fails with SIGSEGV in test_tinyfl
https://github.com/ivmai/bdwgc/issues/167
また、GCJサポートのテストで SEGV が発生する件は、以下で修正されていました。
Issue #137: List reversal produced incorrect list if USE_MUNMAP+GC_GCJ_SUPPORT (Mingw32)
https://github.com/ivmai/bdwgc/issues/137
(この修正は、GitHub上の GC v7.2, v7.4, v7.6 の各ブランチにも水平展開されています。
しかし、ダウンロードページの tar.gz については、古いままのようです。。。)
いずれも、Gauche では未使用のAPIのため、Gauche 本体の実行には影響はありません。
(#166 の関係でまれに gctest が FAIL しますが。。。)
あと、今回の件とは関係ありませんが、気が付いた点として、
GC v7.7 では、include/private/gc_atomic_ops.h というファイルが追加されており、
(Cコンパイラが対応していれば) libatomic_ops なしでビルド可能になっているようです。
(開発版なので安定性等は分かりませんが。。。)
- Shiro(2017/06/22 20:47:53 UTC): ありがとうございます。
MSYS2/MinGW-w64 32bit 開発環境での Gauche のビルド/テストでエラー (0.9.6_pre2)
hamayama(2017/05/07 14:41:57 UTC): 切り分けができていませんが、とりあえず報告しておきます。
MSYS2/MinGW-w64 32bit 開発環境 でのみ現象が発生します。
MSYS2/MinGW-w64 64bit や MinGW.org (32bitのみ) の開発環境では発生しません。
確認した OS は Windows 8.1 (64bit) です。
印象としては、ほとんど動作していて、ごくまれに文字列が化ける感じ。
調査中のメモは、以下に分離しました。
https://gist.github.com/Hamayama/f248c6a8b8e853a49caf58bf1a02399c
(2017/05/09 10:25:44 UTC)
<分かってきたこと>
(1) Gauche v0.9.5 を使って Gauche v0.9.6_pre2 をビルド/テストした場合には発生しない。
(2) (1)で作成した Gauche v0.9.6_pre2 を使って Gauche v0.9.6_pre2 をビルド/テストする際にエラーが出る。
(頻度は、3回ビルド&テストすると1回は出る という程度)
(3) MSYS2/MinGW-w64 32bit の少し古い開発環境 (gcc v6.2.0) でも発生する。
<今後の予定>
git bisect を使って、HEAD と v0.9.5 の間で、現象が発生するようになったコミットを探す。
(時間がかかりそうですが、マイペースですすめてみます。。。)
- Shiro(2017/05/10 07:22:36 UTC):
./DIST self-host-test
をMinGWでも動くようにしました。 これは、まずインストールされたGaucheでソースツリーのGaucheをコンパイルし、次にその新たにコンパイルされたGaucheでソースツリーのGaucheを再びコンパイルして、テストを流します。最初のコンパイル結果は../Gauche-tmp-self-host-test/stage1に、二度めのコンパイル結果は../Gauche-tmp-self-host-test/stage2に置かれます。で、確かに32bitシェルだと変なところでこけますね。(64bitシェルでもテスト失敗がいくつか出ましたが、これはout-of-tree buildの問題っぽい気がする) - Shiro: いや、64bitシェルでも文字列が書き換わってるようなエラーが出るな。 0.9.6_pre2でコンパイルされたものです。
hamayama(2017/05/11 11:59:20 UTC): どうも、今日は、全然再現しなくなってしまいました。。。
昨日までと違うところというと、Windows Update があったので、PC を1回再起動したことです。
引き続き調べてみます。。。
- 齊藤 (2017/05/11 15:18:16 UTC): 私の方でも確認してみましたが、 Windows Update 後に問題が再現しなくなってます。
- Shiro (2017/05/11 23:47:37 UTC): うーむ、Update後64bitシェルで再現しなくなったものの、 32bitシェルでは依然として症状が見られます (./DIST self-host-testでテストした場合)。 うちはWindows 10 Home 64bit version 1607 build 14393.1198っすね。
hamayama(2017/05/13 01:18:27 UTC): 昨日は1回だけ再現しました。頻度が低くなって切り分けが難しい。。。
dllの依存関係もツールで確認したが、問題はなさそう。
これまでのエラーを見ると、いずれもファイルのロードのところで文字化けが起きている。
しかし文字列のテストでは、エラーは発生していない。
シェルもしくはシェルから引数を受け取るところで化ける?
hamayama(2017/05/13 15:54:07 UTC): 再現スクリプトができました。
- args_test.sh
COUNT=0 while :; do gosh -ftest args_test.scm -C -m 555 -T /c/Gauche/Gauche/../Gauche-mingw-dist/Gauche-i686/lib/gauche-0.9/0.9.6_pre2/i686-w64-mingw32 gauche--vport.dll if [ $? -ne 0 ]; then exit 1 fi (( COUNT++ )) echo -n $COUNT" " done
- args_test.scm
(define (main args) (define args0 (map x->string '(-C -m 555 -T C:/Gauche/Gauche/../Gauche-mingw-dist/Gauche-i686/lib/gauche-0.9/0.9.6_pre2/i686-w64-mingw32 gauche--vport.dll))) (define args1 (cdr args)) (unless (equal? args0 args1) (print args1) (exit 1)) (exit 0))
main.c の argc と **argv までは正常に入ってきているもよう。
そこから ScmObj に変換するところで化けているかも。
- Shiro(2017/05/14 08:26:18 UTC): ああああああああああああああ、もしかして!これじゃ!ないですか! https://github.com/shirok/Gauche/commit/e3c684d23113d69cd2df0b95f033fb70bcf9646d
hamayama(2017/05/14 12:33:10 UTC): しばらくスクリプトを動かしていますが大丈夫っぽいです(今40000カウントくらい)。
対応ありがとうございます。齊藤さんもいつも有用な情報ありがとうございます。
(参考 : GC_MALLOC_ATOMIC 関連
http://wiki.monaos.org/pukiwiki.php?Reading%20Gauche%2Fgauche.h%2FSCM_MALLOC_ATOMIC )
- Shiro(2017/05/14 22:05:18 UTC): ありがとうございました。 再現条件を絞って頂いたのが決定的でした。
tls-input-port からの読み込みで ERROR: argument out of range: 1 (0.9.5, HEAD)
shinya 2017/01/11 23:26:22 UTC: tls-read が 1byte だけ読むとマズいようです
パッチ:
diff --git a/ext/tls/tls.scm b/ext/tls/tls.scm index 3d61986..15e3347 100644 --- a/ext/tls/tls.scm +++ b/ext/tls/tls.scm @@ -119,15 +119,13 @@ (set! (~ ip'getb) (let ((buf #f) (pos 0) (size 0)) (^[] - (if buf - (rlet1 r (string-byte-ref buf pos) - (set! pos (+ pos 1)) - (when (= pos size) (set! buf #f))) - (begin - (set! buf (tls-read tls)) - (set! size (string-size buf)) - (set! pos 1) - (string-byte-ref buf 0)))))))) + (unless buf + (set! buf (tls-read tls)) + (set! size (string-size buf)) + (set! pos 0)) + (rlet1 r (string-byte-ref buf pos) + (set! pos (+ pos 1)) + (when (= pos size) (set! buf #f)))))))) (define (make-tls-output-port tls) (rlet1 op (make <virtual-output-port>)
- Shiro(2017/01/12 01:48:16 UTC): まはろ。直しました。https://github.com/shirok/Gauche/commit/857b57bc87b0858ac45237994f99aa8028378519
- Shiro: コード見直してたんだけど、これ相手側がコネクションcloseした時ってどうなるんだったかな。tls-readは必ず1バイト以上読むと仮定して良かったんだっけ。
- shinya: Scm_TLSRead を見ると、返ってくるのは1バイト以上読み込めたときで、その他はエラーを投げると思います。
- Shiro:ああ、ssl_readがSSL_OK(==0)を返した場合は再度ssl_readを呼ぶから0バイト読んで戻ることはないですね。
ただ、相手方がcloseした場合、ssl_readはSSL_CLOSE_NOTIFY(== -3)を返すけどこれはScm_TLSReadが捕まえてエラーにすると。これエラーにしちゃっていいのかな? httpsのクライアントで使ってる限り正常動作時にはEOFを読み出すってことが無いから気づかなかったけど。 - shinya (2017/01/14 02:12:39 UTC): rfc.httpから使っているだけなので気にしていませんでしたが、相手側が閉じた場合はソケットと同じくEOFを返した方が良さそうですね
- shinya: あと、Scm_TLSReadで気になる点が出てきたので書いておきます。
- Scm_SysErrorは呼ばれた時点でのerrnoを見ているので、おかしなエラーを返してしまう
- ソケットがノンブロッキングの場合や読み込みタイムアウトを設定していると、ssl_readがSSL_OKを返すのでwhileで待つことになる
Windows で HEAD のビルドエラー (0.9.5)
hamayama(2016/12/13 08:12:57 UTC): Gauche の HEAD (ec3c709) をビルドして、その Gauche でさらに HEAD をビルドすると、以下のエラーが出ます。
リリース版の Gauche v0.9.5 を使ってビルドした場合には発生しません。
lib/gauche/interpolate.scm を見ると、string-interpolate は定義されているようですが。。。
OS: Windows 8.1 (64bit), 開発環境: MSYS2/MinGW-w64
make[2]: ディレクトリ '/c/Gauche/Gauche/ext/util' に入ります ../../src/gosh -ftest ../../src/precomp -e -P -o util--match ../../libsrc/util/match.scm *** ERROR: Autoloaded symbol string-interpolate is not defined in the module gauche.interpolate While loading "../../libsrc/file/util.scm" at line 856 While compiling "../../lib/gauche/cgen/unit.scm" at line 34: (define-module gauche.cgen.unit (use srfi-13) (use srfi-42) (use util.match) (use file.util) (use gau ... While loading "../../lib/gauche/cgen/unit.scm" at line 56 While compiling "../../lib/gauche/cgen.scm" at line 43: (define-module gauche.cgen (extend gauche.cgen.unit gauche.cgen.literal gauche.cgen.type gauche.cgen. ... While loading "../../lib/gauche/cgen.scm" at line 46 While compiling "../../lib/gauche/cgen/precomp.scm" at line 37: (define-module gauche.cgen.precomp (use srfi-1) (use srfi-13) (use gauche.cgen) (use gauche.cgen.stub ... While loading "../../lib/gauche/cgen/precomp.scm" at line 51 While compiling "./../../src/precomp" at line 40: (use gauche.cgen.precomp) While loading "./../../src/precomp" at line 40 Stack Trace: _______________________________________ make[2]: *** [Makefile:25: util--match.c] エラー 70 make[2]: ディレクトリ '/c/Gauche/Gauche/ext/util' から出ます make[1]: *** [Makefile:37: util] エラー 2 make[1]: ディレクトリ '/c/Gauche/Gauche/ext' から出ます make: *** [Makefile:40: all] エラー 1
- Shiro(2016/12/14 07:20:59 UTC): うわーわかった。コアのSchemeソースファイル(libstr.scmとか) の中でstring interpolationを使ってるので、初期化中にgauche/interpolateを 読んだことになちゃってて改めて読みにいかないんだな。
- Shiro(2016/12/14 09:51:08 UTC):直したー https://github.com/shirok/Gauche/commit/8d1cca0c84a91716457f3ced4c0bcb674156e872
- Gauche組み込みのモジュール (≒ 組み込みライブラリ初期化時に参照されてるモジュール) についてはuseやrequireでファイルを探しに行かれても困るので、初期化の一番最後に既にプロセス中に存在するモジュールを舐めてprovideするようにしている
- しかし、「組み込みライブラリのコンパイル時に使われるマクロ」を外のモジュールから呼んできてるケースがある。マクロは既に展開されてるのでそれらのモジュールはコアに存在する必要はないが、プログラムがuseやrequireしたら読んでこないとならないので、provideしてしまってはまずい。
- これまで、util.matchのみがそれに該当するモジュールだった。先日の変更でgauche.interpolateも加わったのだが、それをこちらの初期化コードに反映するのを忘れてた
- hamayama(2016/12/14 14:45:26 UTC): 修正されていることを確認できました。
TLSで接続できないWEBサーバが存在する (0.9.5)
hamayama(2016/10/29 14:44:21 UTC)(2016/10/31 22:03:42 UTC): https://syosetu.org/ に接続しようとすると以下のエラーが発生する件について調べました。
(use rfc.http) (http-get "syosetu.org" "/" :secure #t) *** ERROR: TLS handshake failed: -40
これは、axTLS v2.0.1 がサポートする cipher suite と、WEBサーバがサポートする cipher suite に一致するものが存在しないためのようです。
axTLS v2.0.1 がサポートする cipher suite は、以下の4個になります。
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) TLS_RSA_WITH_AES_256_CBC_SHA (0x35) TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c) TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d)
一方、https://syosetu.org/ については、SSL Server Test ( https://www.ssllabs.com/ssltest/index.html ) のページで確認すると、
これらの cipher suite をサポートしていません。
このため、TLS の client hello メッセージに対して、SSL_ALERT_HANDSHAKE_FAILURE (40) が返って、エラーになります。
また、Gauche v0.9.4 の場合には、axTLS v1.4.9 を使用しており、サポートする cipher suite は、以下の4個になります。
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) TLS_RSA_WITH_AES_256_CBC_SHA (0x35) TLS_RSA_WITH_RC4_128_SHA (0x5) TLS_RSA_WITH_RC4_128_MD5 (0x4)
このうちの TLS_RSA_WITH_RC4_128_SHA (0x5) については、https://syosetu.org/ でもサポートしているため、通信が成功します。
ただし、RC4 は INSECURE とのことで、現在は使用が推奨されていないようです。
今後どうすればよいかですが。。。
基本的には、TLSのライブラリで、
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
のような新しいタイプの cipher suite がサポートされるのがよさそうではあります。
ECDHE は FS (Forward secrecy) という性質を持つ鍵交換プロトコルであり、GCM は 認証付き暗号モードとのことで、
実現が難しいかもしれませんが。。。
あとは、WEBサーバ側に、axTLS v2.0.1 の cipher suite を追加してもらうよう依頼することも考えられます。
ただし、多くのブラウザでは ECDHE 等が使用できるようなので、理由を聞かれるかもしれませんが。。。
(google.com, microsoft.com, www.apple.com 等、多くのサーバは axTLS v2.0.1 の cipher suite をサポートしているのですが。。。)
- hamayama(2016/10/30 12:12:30 UTC):暫定の対策として、stunnel ( https://www.stunnel.org/ ) というソフトを使ってみました。
インストール後に、stunnel.conf の元の内容を全部コメントアウトしてから、以下を記述して、実行しました。[http-https] client = yes accept = 127.0.0.1:10080 connect = syosetu.org:443 verifyChain = yes CAfile = ca-certs.pem checkHost = syosetu.org OCSPaia = yes
そして、Gauche v0.9.5 から以下を実行したところ、うまく接続できたようです。(use rfc.http) (http-get "syosetu.org" "/" :proxy "127.0.0.1:10080")
(2016-11-1 修正。http-get で :proxy を使わないと、サーバ名ではじかれていました。。。(2016/11/01 13:54:15 UTC))
- Shiro(2016/11/01 01:06:27 UTC): 調査ありがとうございます。stunnelはaxtls採用前にhttps通信に使っていました。フォールバックとして復活させる手もありますね。axtlsだけでいけるのが楽ではあるのですが… コミット 50fdef91fb2df9c7fc3a68b33ee2886179510551 でstunnelのサポートを落としてaxtlsに切りかえています。
- Shiro(2017/01/13 07:33:34 UTC): stunnelを使ったhttpsのサポートも復活させてみました。 secureキーワード引数に'stunnelを渡すとstunnelを使います。
- hamayama(2020/04/25 06:41:43 UTC):その後、Gauche 0.9.6 から、
mbedTLS という C の TLS ライブラリが使えるようになっています (#350)。
https://github.com/shirok/Gauche/blob/master/INSTALL.adoc#tlsssl-support
を参照ください。
(ライブラリのインストール後、Gauche の再コンパイルが必要です。
(Windows の場合には、src/mingw-dist.sh 内の configure のオプションの
--with-tls=axtls を消してビルドする必要があります))
使用例は以下のようになります。
( cacert.pem は、https://curl.haxx.se/ca/cacert.pem から取得できるようです)(use rfc.tls) (default-tls-class <mbed-tls>) (tls-ca-bundle-path "c:\\work\\ca\\cacert.pem") (use rfc.http) (receive (status header-list body) (http-get "syosetu.org" "/" :secure #t) (print status))