外部プロセスと対話する C++ プログラムを作成しています。外部プロセスは C# で記述されており、mono で実行されます。私が作成したプログラムではないため、C# コードを変更することはできません。
この点に関して、私は最初にパイプを使用することから始めました。もちろん後で気づいたように、パイプは完全にバッファリングされているため、多くの同期の問題に直面しました。基本的に、外部プロセスは書き込みごとに出力をフラッシュする必要があり、これは不可能でした。
次に試したのはファイルでしたが、私の場合は疑似端末を使用する方が適していることがわかりました。ここに私が書いたいくつかのサンプルコードがあります:
int main()
{
int fdm, fds, rc, pid;
bool rValue;
/* Setup Master pty*/
rValue = rValue && (fdm = posix_openpt(O_RDWR)) >= 0 &&
(rc = grantpt(fdm)) == 0 && (rc = unlockpt(fdm) == 0);
if (rValue) {
/* Open Slave pty */
fds = open(ptsname(fdm), O_RDWR);
pid = fork();
if(pid < 0)
perror("fork failed");
else if(pid == 0) //child
{
close(fdm); //close master
struct termios slave_orig_term_settings;
struct termios new_term_settings;
tcgetattr(slaveTTY, &slave_orig_term_settings);
new_term_settings = slave_orig_term_settings;
cfmakeraw(&new_term_settings);
tcsetattr(slaveTTY, TCSANOW, &new_term_settings);
//redirect I/O of this process
close(0);
close(1);
close(2);
dup(slaveTTY);
dup(slaveTTY);
dup(slaveTTY);
close(slaveTTY);
setsid();
ioctl(0, TIOCSCTTY, 1);
//launch the external process and replace its image in this process
execve(argv[0],...);
}
else
{
close(fds); //close slave
//Perform some interaction
write(something using fdm);
//Assume fdsets declared and set somewhere here
select(fdm +1,&fdset,NULL,NULL,NULL);
int readBytes = read(someting using fds);
}
}
return EXIT_SUCCESS;
}
select の fdset と fdclr が処理されているとします。
親プロセスで次の問題が確認されています。
- readBytes > 0 で read が返されることがありますが、バッファには何もありません。
- ターミナルに書き込まれたものが読み戻されることがあります
- ^]]49]1R などの一部のガベージ値が端末にダンプされています (これは実際の端末、つまり出力ウィンドウです)
PS: 外部プロセスが C/C++ で記述されている場合、この問題は発生しません。C# プログラムを mono で実行した場合のみ。