2012-02-20 22 views
5

私はprocess-send-stringを使用してソケット接続にデータを送信していますが、この機能の効果に満足していません。おおよそ(process-send-string "foo")と呼び出すと、"bar"が送信され、次に"foo"が送信されます。アトミックにソケットに書き込む

としては、Emacsのメンテナが指摘し、process-send-stringのCコードが機能wait_reading_process_output呼び出す順番にprocess-send-stringを呼ぶ可能性がある、タイマーを実行することができ、そして何の順序は、このようなネストされた呼び出しの間で施行されていない、(でも、実際には何を書き込む前に)。

これは、制御されていない時間に呼び出されたフックによって使用されることを意図したRPCプロトコルを実装することを事実上不可能にします。ですから、私の質問は、この目的のためにどのように原子同期の "書き込み"プリミティブを達成できるのでしょうか?

+1

実際にその影響を経験しましたか? Emacsのソースコードを一見すると、データをソケットに一度に書き込むことができず、 'sendto 'を複数回呼び出す必要があると、記述したケースが発生する可能性があります。これらの呼び出しのたびに、キーボードイベントと再表示を処理するために 'wait_reading_process_output 'が呼び出されます。その関数内で使用されたタイマーが 'process-send-string 'をもう一度呼び出すことができるかどうかはわかりません。 – Thomas

+0

はい、私は以下を見てきました:m1、m2、m3を送信すると、接続端はm2、m3、m1を受信します。 –

+0

TCPはパケット指向ではなく、バイト指向であることに注意してください。アプリケーションが「1234」を書き込む場合、TCPスタックは、可能なセグメンテーション、例えば「12」、「3」、「4」でこれを送ることができる。 TCPより上のプロトコルを実行する場合は、メッセージの境界を見つける方法を定義する必要があります。長さフィールドを使用します。 – bew

答えて

1

最後に、私のために働いたオプションは、より高いレベルの(すべての種類のプロトコルを処理できないように)トランザクションキューAPIを使用することでしたが、交互のメッセージの正しい順序付けを保証します。

2

process-send-stringをフックで直接使用するのではなく、バッファに追加してからprocess-send-string呼び出しを非同期で実行するようにしてください。

+1

"非同期ではない方法でprocess-send-string呼び出しを実行する方法は? –

3

あなたのような何かを行うことができます:あなたはコマンドに対する答えを得るとき、私は、保留中」と非nilの、最初の引数を取る場合、 `チェック、プロセス・フィルタで、その後

(defun my-send-cmd (proc str) 
    (if (process-get proc 'my-waiting) 
     (process-put proc 'my-pending (append (process-get proc 'my-pending) (list str))) 
    (process-put proc 'my-waiting t) 
    (process-send-string proc str))) 

をそれをプロセスに送ってください。それ以外の場合は、待機待ちをnilに戻してください。 もちろん、これはすべてのコマンドがサーバーから応答を受け取り、コマンドをストリーミングできないことを前提としています。

これは、あなたが見ている動作は、おそらくバグとして、または少なくとも誤ったものとしてカウントされるはずだから、M-x report-emacs-bugで報告してください。

+0

これはうまくいくように思えます:プロトコルの通信はまだ機能しています。メッセージのスワップはもう観察できませんので、リリースから一時間にこの重要な問題を解決して私の人生を救いました:-) –

+0

「送信スレッド」としてプロセスフィルタを使用することは、私が見逃していたものであり、常にメッセージが交互に表示されるため、ここでうまく動作します。 –

+0

バグ報告について、私は1つを送っていくつかの短いフィードバックを得ましたが、それはバグ、間違ったものであるかどうかはまだ分かりません。私は明確な答えを得ることを確認します。 –

関連する問題