kess
kess

Reputation: 1309

Dart don't buffer process stdout (tell process that it is running from a terminal)

I'm trying to run a binary file width Process.start in dart and redirect its output the stdout and pipe stdin to the process.

Here is my code:

import 'dart:io';
import 'dart:convert';

main() async {
  Process.start('./test.bin', []).then((p) {
    p.stdout.listen((bytes) {
      stdout.add(bytes);
      stdout.flush();
    });
    stdin.pipe(p.stdin);
  });
}

The problem is that it only flushes the process's stdout after the process terminates.

After digging around on the internet I found this: "This is caused by libc which by default puts stdout int buffered mode when it is not connected to a terminal."

How could I tell the process that it is running from a terminal?

My goal with this project is to have a terminal in a webapp that interacts with this process running on the backend, so it will be running on a terminal but the process is obviously unaware of that.

Upvotes: 0

Views: 770

Answers (3)

Mehran
Mehran

Reputation: 2027

This code redirects all stdio streams from a new process. It has a few details

  1. It checks for the availability of terminal and pipes the standard input if available.
  2. It switches the line mode off so that the data from stdio does not gets buffered before receiving the Enter key.

Code:

final child = await Process.start(command, args, runInShell: true);

if (stdin.hasTerminal) {
  stdin.lineMode = false;
  unawaited(stdin.pipe(child.stdin));
}
unawaited(child.stdout.pipe(stdout));
unawaited(child.stderr.pipe(stderr));

if (await child.exitCode != 0) {
  throw Exception(
    'Failed to execute $command ${args.join(' ')}: with code ${await child.exitCode}',
  );
}

Upvotes: 0

Raj
Raj

Reputation: 1

NodeJS is more better in case of child process management. But i think you can fix your code with use of some types buffer splitting. Example of Split by line:-

var process = await Process.start(cmd, param,
        environment: env,
        includeParentEnvironment: true,
        runInShell: true,
        mode: ProcessStartMode.normal);
    Stream<String> readLine() => process.stdout
        .transform(utf8.decoder)
        .transform(const LineSplitter());
    readLine().listen(callback);
    var exitcode = await process.exitCode;
    print("Process Exit:- " + exitcode);

Upvotes: 0

kess
kess

Reputation: 1309

I'm answering my own question in case anyone finds this post.

I ended up writing the backend in nodejs with the help of this library (https://www.npmjs.com/package/node-pty)

But I found a similar library for dart as well (https://pub.dev/packages/pty)

Upvotes: 1

Related Questions