summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.c10
-rw-r--r--lsp.c29
-rw-r--r--main.c1
-rw-r--r--os-posix.c44
-rw-r--r--os-win.c14
-rw-r--r--os.h8
-rw-r--r--ted.cfg3
7 files changed, 84 insertions, 25 deletions
diff --git a/build.c b/build.c
index 56bc316..556cffb 100644
--- a/build.c
+++ b/build.c
@@ -5,7 +5,7 @@
void build_stop(Ted *ted) {
if (ted->building)
- process_kill(ted->build_process);
+ process_kill(&ted->build_process);
ted->building = false;
ted->build_shown = false;
arr_foreach_ptr(ted->build_errors, BuildError, err) {
@@ -36,6 +36,7 @@ void build_queue_command(Ted *ted, const char *command) {
static bool build_run_next_command_in_queue(Ted *ted) {
if (!ted->build_queue)
return false;
+ assert(!ted->build_process);
assert(*ted->build_dir);
change_directory(ted->build_dir);
char *command = ted->build_queue[0];
@@ -243,7 +244,6 @@ void build_check_for_errors(Ted *ted) {
void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
TextBuffer *buffer = &ted->build_buffer;
- Process *process = ted->build_process;
assert(ted->build_shown);
char buf[256];
if (ted->building) {
@@ -254,9 +254,9 @@ void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
memcpy(incomplete, ted->build_incomplete_codepoint, sizeof incomplete);
*ted->build_incomplete_codepoint = 0;
- i64 bytes_read = (i64)process_read(process, buf + 3, sizeof buf - 3);
+ i64 bytes_read = (i64)process_read(ted->build_process, buf + 3, sizeof buf - 3);
if (bytes_read == -2) {
- ted_error(ted, "Error reading command output: %s.", process_geterr(process));
+ ted_error(ted, "Error reading command output: %s.", process_geterr(ted->build_process));
build_stop(ted);
break;
} else if (bytes_read == -1) {
@@ -302,7 +302,7 @@ void build_frame(Ted *ted, float x1, float y1, float x2, float y2) {
}
char message[64];
- int status = process_check_status(process, message, sizeof message);
+ int status = process_check_status(&ted->build_process, message, sizeof message);
if (status == 0) {
// hasn't exited yet
} else {
diff --git a/lsp.c b/lsp.c
index 6fb1d15..1cbe9e6 100644
--- a/lsp.c
+++ b/lsp.c
@@ -268,7 +268,8 @@ const char *lsp_response_string(const LSPResponse *response, LSPString string) {
}
// receive responses/requests/notifications from LSP, up to max_size bytes.
-static void lsp_receive(LSP *lsp, size_t max_size) {
+// returns false if the process exited
+static bool lsp_receive(LSP *lsp, size_t max_size) {
{
// read stderr. if all goes well, we shouldn't get anything over stderr.
@@ -287,13 +288,26 @@ static void lsp_receive(LSP *lsp, size_t max_size) {
}
}
}
+
+ {
+ // check process status
+ char text[64] = {0};
+ int status = process_check_status(&lsp->process, text, sizeof text);
+ if (status != 0) {
+ lsp_set_error(lsp, "Can't access LSP server: %s\n"
+ "Run ted in a terminal or set lsp-log = on for more details."
+ , text);
+ return false;
+ }
+
+ }
size_t received_so_far = arr_len(lsp->received_data);
arr_reserve(lsp->received_data, received_so_far + max_size + 1);
long long bytes_read = process_read(lsp->process, lsp->received_data + received_so_far, max_size);
if (bytes_read <= 0) {
// no data
- return;
+ return true;
}
received_so_far += (size_t)bytes_read;
// kind of a hack. this is needed because arr_set_len zeroes the data.
@@ -334,6 +348,7 @@ static void lsp_receive(LSP *lsp, size_t max_size) {
arr_reserve(lsp->received_data, leftover_data_len + 1);
lsp->received_data[leftover_data_len] = '\0';
}
+ return true;
}
// send requests.
@@ -388,11 +403,17 @@ static int lsp_communication_thread(void *data) {
bool quit = lsp_send(lsp);
if (quit) break;
- lsp_receive(lsp, (size_t)10<<20);
+ if (!lsp_receive(lsp, (size_t)10<<20))
+ break;
if (SDL_SemWaitTimeout(lsp->quit_sem, 5) == 0)
break;
}
+ if (!lsp->process) {
+ // process already exited
+ return 0;
+ }
+
if (lsp->initialized) {
LSPRequest shutdown = {
.type = LSP_REQUEST_SHUTDOWN,
@@ -556,7 +577,7 @@ void lsp_free(LSP *lsp) {
SDL_DestroyMutex(lsp->workspace_folders_mutex);
SDL_DestroyMutex(lsp->error_mutex);
SDL_DestroySemaphore(lsp->quit_sem);
- process_kill(lsp->process);
+ process_kill(&lsp->process);
arr_free(lsp->received_data);
diff --git a/main.c b/main.c
index 85d1a6f..7d9c287 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,5 @@
/*
@TODO:
-- check LSP process status (TEST: what happens if LSP server is not installed)
- make tags_dir the root folder
- check that tags still works
- check that phantom completions works with tags
diff --git a/os-posix.c b/os-posix.c
index 3f19534..f34d33b 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -245,10 +245,15 @@ Process *process_run(const char *command) {
const char *process_geterr(Process *p) {
+ if (!p) return "no such process";
return *p->error ? p->error : NULL;
}
long long process_write(Process *proc, const char *data, size_t size) {
+ if (!proc) {
+ assert(0);
+ return -2;
+ }
if (!proc->stdin_pipe) { // check that process hasn't been killed
strbuf_printf(proc->error, "Process terminated");
return -2;
@@ -299,10 +304,18 @@ static long long process_read_fd(Process *proc, int fd, char *data, size_t size)
}
long long process_read(Process *proc, char *data, size_t size) {
+ if (!proc) {
+ assert(0);
+ return 0;
+ }
return process_read_fd(proc, proc->stdout_pipe, data, size);
}
long long process_read_stderr(Process *proc, char *data, size_t size) {
+ if (!proc) {
+ assert(0);
+ return 0;
+ }
return process_read_fd(proc, proc->stderr_pipe, data, size);
}
@@ -313,44 +326,59 @@ static void process_close_pipes(Process *proc) {
proc->stdin_pipe = 0;
proc->stdout_pipe = 0;
proc->stderr_pipe = 0;
+ proc->pid = 0;
}
-void process_kill(Process *proc) {
+void process_kill(Process **pproc) {
+ Process *proc = *pproc;
+ if (!proc) return;
+
kill(-proc->pid, SIGKILL); // kill everything in process group
// get rid of zombie process
waitpid(proc->pid, NULL, 0);
- proc->pid = 0;
process_close_pipes(proc);
free(proc);
+ *pproc = NULL;
}
-int process_check_status(Process *proc, char *message, size_t message_size) {
+int process_check_status(Process **pproc, char *message, size_t message_size) {
+ Process *proc = *pproc;
+ if (!proc) {
+ assert(0);
+ if (message) str_printf(message, message_size, "checked status twice");
+ return -1;
+ }
+ assert(!message || message_size > 0);
int wait_status = 0;
int ret = waitpid(proc->pid, &wait_status, WNOHANG);
if (ret == 0) {
// process still running
+ if (message)
+ *message = '\0';
return 0;
} else if (ret > 0) {
if (WIFEXITED(wait_status)) {
- process_close_pipes(proc);
+ process_kill(pproc);
int code = WEXITSTATUS(wait_status);
if (code == 0) {
- str_printf(message, message_size, "exited successfully");
+ if (message) str_printf(message, message_size, "exited successfully");
return +1;
} else {
- str_printf(message, message_size, "exited with code %d", code);
+ if (message) str_printf(message, message_size, "exited with code %d", code);
return -1;
}
} else if (WIFSIGNALED(wait_status)) {
process_close_pipes(proc);
- str_printf(message, message_size, "terminated by signal %d", WTERMSIG(wait_status));
+ if (message)
+ str_printf(message, message_size, "terminated by signal %d", WTERMSIG(wait_status));
return -1;
}
return 0;
} else {
// this process is gone or something?
process_close_pipes(proc);
- str_printf(message, message_size, "process ended unexpectedly");
+ if (message)
+ str_printf(message, message_size, "process ended unexpectedly");
return -1;
}
}
diff --git a/os-win.c b/os-win.c
index 0e88e68..d7f29ca 100644
--- a/os-win.c
+++ b/os-win.c
@@ -6,6 +6,7 @@
#include <io.h>
#include <sysinfoapi.h>
+
static FsType windows_file_attributes_to_type(DWORD attrs) {
if (attrs == INVALID_FILE_ATTRIBUTES)
return FS_NON_EXISTENT;
@@ -129,6 +130,7 @@ void time_sleep_ns(u64 ns) {
Sleep((DWORD)(ns / 1000000));
}
+#error "@TODO: fix process functions to take Process**"
#error "@TODO : implement process_write, separate_stderr, working_directory"
#error "@TODO : make sure process_read & process_write do what they're supposed to for both blocking & non-blocking read/writes."
#include "process.h"
@@ -244,24 +246,30 @@ void process_kill(Process *process) {
}
int process_check_status(Process *process, char *message, size_t message_size) {
+ assert(!message || message_size);
HANDLE hProcess = process->process_info.hProcess;
DWORD exit_code = 1;
if (GetExitCodeProcess(hProcess, &exit_code)) {
if (exit_code == STILL_ACTIVE) {
+ if (message)
+ *message = '\0';
return 0;
} else {
process_kill(process);
if (exit_code == 0) {
- str_printf(message, message_size, "exited successfully");
+ if (message)
+ str_printf(message, message_size, "exited successfully");
return +1;
} else {
- str_printf(message, message_size, "exited with code %d", (int)exit_code);
+ if (message)
+ str_printf(message, message_size, "exited with code %d", (int)exit_code);
return -1;
}
}
} else {
// something has gone wrong.
- str_printf(message, message_size, "couldn't get process exit status");
+ if (message)
+ str_printf(message, message_size, "couldn't get process exit status");
process_kill(process);
return -1;
}
diff --git a/os.h b/os.h
index b7d189e..20135ff 100644
--- a/os.h
+++ b/os.h
@@ -123,10 +123,12 @@ long long process_read_stderr(Process *process, char *data, size_t size);
// 1 if the process exited successfully
// 0 if the process hasn't exited.
// If message is not NULL, it will be set to a description of what happened (e.g. "exited successfully")
-int process_check_status(Process *process, char *message, size_t message_size);
+// if the process is no longer running, *process will be freed and set to NULL.
+int process_check_status(Process **process, char *message, size_t message_size);
// kills process if still running
-// this also frees any resources used by `process`.
-void process_kill(Process *process);
+// this also frees any resources used by `*process`.
+// *process will be set to NULL.
+void process_kill(Process **process);
#endif // OS_H_
diff --git a/ted.cfg b/ted.cfg
index 8d571c1..c316ff3 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -40,7 +40,8 @@ phantom-completions = on
lsp-enabled = yes
# enable this to log all messages between ted and the LSP server
# (may require restarting ted to update)
-lsp-log = yes
+# the log file is in the same folder as ted.cfg.
+lsp-log = off
# display function signature help? (only with LSP running)
# this is the thing at the bottom of ted which shows the parameters to the function you're calling
signature-help-enabled = yes