Commit graph

6 commits

Author SHA1 Message Date
Leroy Hopson
9ed6750b83
Fix unicode errors
Changes `write()` method of native pipe and terminal to accept a
PoolByteArray rather than String. This means that `get_string_from_utf8()`
is no longer called on data coming from PTY and being sent to Terminal.

The terminal state machine already has a UTF8 parser which maintains
its state across calls to `write()`. This means that we can write half
the bytes of a single unicode character in one call and the remaining half
in the next call and the state machine will parse it correctly.

On the other hand, the `get_string_from_utf8()` method of Godot's
PoolByteArray requires that the array contains completely valid UTF8,
otherwise we get errors such as "Unicode error: invalid skip".

The data coming from PTY can be arbitrarily split in the middle of a
unicode character meaning that we will sometimes get errors when calling
`get_string_from_utf8()` on it. This is more likely to occur when there
is a large amount of output (i.e. it's more likely to be split). In other
cases, the data might intentionally contain invalid unicode such as when
printing binary files or random data (e.g. `cat /bin/sh`, `cat /dev/random`).

We avoid these errors by passing the PoolByteArray data directly to the terminal
state machine.

In addition to fixing unicode errors, this commit:
- Prevents repeated calls to pipes `_read_cb()` method that would block Godot
  and result in a crash with the message "ERROR: All memory pool allocations
  are in use" that resulted from writing data to an ever-increasing number of
  PoolByteArrays before any of them could be freed. This could be triggered by
  running the `cat /dev/urandom` command after making the change to `write()`
  mentioned above.
- Prevents memory leaks by freeing libuv buffers after they have been copied
  to PoolByteArrays.

Fixes #55.
2022-08-15 17:09:29 +12:00
Leroy Hopson
0ae1d80abb
Prevent exit callback instance leaks
De-references pty_baton's exit callback after it is called so it can be
automatically released, preventing leaked instances.

Adds basic implementation for Pipe's get_status() method and forces PTY
to wait for child process to exit to ensure exit callback is cleaned up.

Adds a test to check that exit callback is still called as usual.
2022-07-11 09:33:01 +12:00
Leroy Hopson
1d51acb38d
Register pipe.close() method
Allows kill() method of unix PTY node to be called without error.
2022-07-11 09:33:00 +12:00
Leroy Hopson
c81da3820b
Kill child process and close pty on exit
- Adds kill() method to LibuvUtils.
- Adds close() method to Pipe.
2021-07-23 08:37:54 +07:00
Leroy Hopson
84243cd824
Enable compiling Pipe and LibuvUtils on Windows
Currently only works when building with debug target. On GitHub actions
target release results in linking errors. So disable PTY for release
builds.

Part of #25.
2021-07-18 15:09:21 +07:00
Leroy Hopson
0dd2378387 Add new PTY node (replaces Pseudoterminal node)
Uses fork of node-pty native code for forking pseudoterminals.
Uses libuv pipe handle to communicate with the child process.

- Paves the way for cross-platform (Linux, macOS and Windows) support.
- Renames Pseudoterminal to PTY (which is much easier to type and spell :D).
- Better performance than the old Pseudoterminal node. Especially when
  streaming large amounts of data such as running the `yes` command.
- Allows setting custom file, args, initial window size, cwd, env vars
  (including important ones such as TERM and COLORTERM) and uid/gid
  on Linux and macOS.
- Returns process exit code and terminating signal.
2021-07-03 14:56:27 +07:00