Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ LIB_SRC = $(shell pwd)/lib
LIBUV_SRC = $(shell pwd)/3rd_party/libuv-1.51.0
LIBUV_BUILD_DIR = $(MIX_APP_PATH)/cmake_libuv-1.51.0
LIBUV_INSTALL_DIR = $(MIX_APP_PATH)/libuv
LIBUV_A = $(LIBUV_INSTALL_DIR)/lib/libuv_a.a
LIBUV_A = $(LIBUV_INSTALL_DIR)/lib/libuv.a
LIBUV_CMAKE_SOURCE_DIR = $(LIBUV_INSTALL_DIR)/cmake/libuv
NIF_BUILD_DIR = $(MIX_APP_PATH)/cmake_expty
NIF_SOURCES = $(shell find "$(C_SRC)" -type f) CMakeLists.txt

DEFAULT_JOBS ?= 1
MAKE_BUILD_FLAGS ?= -j$(DEFAULT_JOBS)

.DEFAULT_GLOBAL := build
.DEFAULT_GOAL := build

build: $(NIF_SO)
@ echo > /dev/null
Expand All @@ -32,9 +33,8 @@ $(LIBUV_A): $(PRIV_DIR)
cmake --install . ; \
fi

$(NIF_SO): $(PRIV_DIR) $(LIBUV_A)
@ if [ ! -e "$(NIF_SO)" ]; then \
mkdir -p "$(NIF_BUILD_DIR)" && \
$(NIF_SO): $(PRIV_DIR) $(LIBUV_A) $(NIF_SOURCES)
@ mkdir -p "$(NIF_BUILD_DIR)" && \
cd "$(NIF_BUILD_DIR)" && \
cmake "$(shell pwd)" -D CMAKE_INSTALL_PREFIX="$(PRIV_DIR)" \
-D LIBUV_INCLUDE_DIR="$(LIBUV_INSTALL_DIR)/include" \
Expand All @@ -46,8 +46,7 @@ $(NIF_SO): $(PRIV_DIR) $(LIBUV_A)
-D PRIV_DIR="$(PRIV_DIR)" \
-D ERTS_INCLUDE_DIR="$(ERTS_INCLUDE_DIR)" && \
cmake --build . $(MAKE_BUILD_FLAGS) && \
cmake --install . ; \
fi
cmake --install .

cleanup:
@ rm -rf "$(PRIV_DIR)"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
**(Warning: this project is still WIP, there are a lot of things (like proper cleanups) not done yet, and right now it shows a minimal working product (without proper cleanups yet!) with Kino. Use at your own risk.**
**Warning:** this project is still WIP. Some cleanup paths are still incomplete, and the Kino integration currently demonstrates a minimal working product. Use at your own risk.

**Any help/PR is welcome!**

Expand All @@ -15,8 +15,8 @@
<td>

```elixir
iex> pty = ExPTY.spawn("tty", [], on_data: fn _, _, data -> IO.write(data) end)
#PID<0.229.0>
iex> {:ok, pty} = ExPTY.spawn("tty", [], on_data: fn _, _, data -> IO.write(data) end)
{:ok, #PID<0.229.0>}
/dev/ttys001
```

Expand Down Expand Up @@ -100,7 +100,7 @@ by adding `ExPTY` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:expty, "~> 0.1.0"}
{:expty, "~> 0.2.2"}
]
end
```
Expand Down
32 changes: 24 additions & 8 deletions c_src/unix/pty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ pty_pipesocket_fn(void *data) {
const size_t buf_size = 1024;
char buffer[buf_size] = {'\0'};
ssize_t bytes_read = read(fd, buffer, buf_size);

if (bytes_read == 0) {
pipesocket->fd_closed = true;
close(fd);
Expand All @@ -648,15 +649,17 @@ pty_pipesocket_fn(void *data) {

ERL_NIF_TERM dataread;
unsigned char * ptr;
size_t bytes_read_size = static_cast<size_t>(bytes_read);

ErlNifEnv * msg_env = enif_alloc_env();
if ((ptr = enif_make_new_binary(msg_env, bytes_read, &dataread)) != nullptr) {
memcpy(ptr, buffer, bytes_read);
if ((ptr = enif_make_new_binary(msg_env, bytes_read_size, &dataread)) != nullptr) {
memcpy(ptr, buffer, bytes_read_size);
enif_send(NULL, &pipesocket->process, msg_env, enif_make_tuple2(msg_env,
nif::atom(msg_env, "data"),
dataread
));
}

enif_free_env(msg_env);
}
}
Expand All @@ -670,10 +673,11 @@ size_t pty_pipesocket::write(void * data, size_t len) {
}

uv_mutex_lock(&this->mutex);
const char *buffer = static_cast<const char *>(data);
size_t bytes_to_write = len, bytes_written = 0, buffer_size = 1024, nbytes = 0;
size_t retry = 3;

while (true) {
while (bytes_written < len) {
nbytes = buffer_size;
if (buffer_size > bytes_to_write) {
nbytes = bytes_to_write;
Expand All @@ -683,18 +687,30 @@ size_t pty_pipesocket::write(void * data, size_t len) {
break;
}

ssize_t bytes_written_cur = ::write(this->fd, static_cast<char *>(data) + bytes_written, nbytes);
ssize_t bytes_written_cur = ::write(this->fd, buffer + bytes_written, nbytes);
if (bytes_written_cur > 0) {
bytes_written += bytes_written_cur;
bytes_to_write -= bytes_written_cur;
retry = 3;
if (bytes_written == len) {
break;
}
} else {
if (retry-- > 0) {
usleep(10);
}
continue;
}

if (bytes_written_cur == -1 && errno == EINTR) {
continue;
}

if (bytes_written_cur == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
retry > 0) {
retry--;
usleep(10);
continue;
}

break;
}

uv_mutex_unlock(&this->mutex);
Expand Down
Loading
Loading