aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/channel.c')
-rw-r--r--src/nvim/channel.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 7a08ba58d0..22eb31513d 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -499,48 +499,54 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output,
}
/// @param data will be consumed
-size_t channel_send(uint64_t id, char *data, size_t len, const char **error)
+size_t channel_send(uint64_t id, char *data, size_t len,
+ bool data_owned, const char **error)
{
Channel *chan = find_channel(id);
+ size_t written = 0;
if (!chan) {
*error = _(e_invchan);
- goto err;
+ goto retfree;
}
if (chan->streamtype == kChannelStreamStderr) {
if (chan->stream.err.closed) {
*error = _("Can't send data to closed stream");
- goto err;
+ goto retfree;
}
// unbuffered write
- size_t written = fwrite(data, len, 1, stderr);
- xfree(data);
- return len * written;
+ written = len * fwrite(data, len, 1, stderr);
+ goto retfree;
}
if (chan->streamtype == kChannelStreamInternal && chan->term) {
terminal_receive(chan->term, data, len);
- return len;
+ written = len;
+ goto retfree;
}
Stream *in = channel_instream(chan);
if (in->closed) {
*error = _("Can't send data to closed stream");
- goto err;
+ goto retfree;
}
if (chan->is_rpc) {
*error = _("Can't send raw data to rpc channel");
- goto err;
+ goto retfree;
}
- WBuffer *buf = wstream_new_buffer(data, len, 1, xfree);
+ // write can be delayed indefinitely, so always use an allocated buffer
+ WBuffer *buf = wstream_new_buffer(data_owned ? data : xmemdup(data, len),
+ len, 1, xfree);
return wstream_write(in, buf) ? len : 0;
-err:
- xfree(data);
- return 0;
+retfree:
+ if (data_owned) {
+ xfree(data);
+ }
+ return written;
}
/// Convert binary byte array to a readfile()-style list