diff --git a/src/lib/mysql-connector.cpp b/src/lib/mysql-connector.cpp index 387aeee..2664bfa 100644 --- a/src/lib/mysql-connector.cpp +++ b/src/lib/mysql-connector.cpp @@ -99,35 +99,36 @@ String mysql_escape(String raw, char quote_char) DValue field_to_dv_node(char* data_ptr, MySQLFieldInfo field_info, u32 len) { DValue result; + if(data_ptr == 0) + return(result); + String raw(data_ptr, len); switch(field_info.type) { case(MYSQL_TYPE_TINY): - result.set(atoll(data_ptr)); + result.set(atoll(raw.c_str())); break; case(MYSQL_TYPE_SHORT): - result.set(atoll(data_ptr)); + result.set(atoll(raw.c_str())); break; case(MYSQL_TYPE_LONG): - result.set(atoll(data_ptr)); + result.set(atoll(raw.c_str())); break; case(MYSQL_TYPE_INT24): - result.set(atoll(data_ptr)); + result.set(atoll(raw.c_str())); break; case(MYSQL_TYPE_LONGLONG): - result.set(atoll(data_ptr)); + result.set(atoll(raw.c_str())); break; case(MYSQL_TYPE_FLOAT): - result.set(atof(data_ptr)); + result.set(atof(raw.c_str())); break; case(MYSQL_TYPE_DOUBLE): - result.set(atof(data_ptr)); + result.set(atof(raw.c_str())); break; case(MYSQL_TYPE_NULL): break; default: - String s; - s.assign(data_ptr); - result.set(s); + result.set(raw); break; } return(result); diff --git a/src/lib/sys.cpp b/src/lib/sys.cpp index 7c30b8a..3bb99e1 100644 --- a/src/lib/sys.cpp +++ b/src/lib/sys.cpp @@ -36,7 +36,7 @@ size_t uce_host_memcache_command(uint64_t sockfd, const char* command, size_t co size_t uce_host_mysql(const char* in, size_t in_len, char* out, size_t cap); size_t uce_host_request_perf(const char* in, size_t in_len, char* out, size_t cap); size_t uce_host_shell_exec(const char* cmd, size_t cmd_len, char* buf, size_t cap); -int uce_host_file_open_locked(const char* path, size_t path_len, int open_flags, int lock_type, int create_mode, double wait_timeout_seconds, const char* purpose, size_t purpose_len); +int uce_host_file_open_locked(const char* path, size_t path_len, int open_flags, int lock_type, int create_mode, double wait_timeout_seconds, const char* purpose, size_t purpose_len, const char* current, size_t current_len); void uce_host_file_close_locked(int handle); void uce_host_file_release_process_locks(const char* reason, size_t reason_len); size_t uce_host_file_read_locked_fd(int handle, char* buf, size_t cap); @@ -105,9 +105,10 @@ bool file_exists(String path) } int file_open_locked(String file_name, int open_flags, int lock_type, int create_mode, f64 wait_timeout_seconds, String purpose) { + String current = wasm_current_unit_file(); return(uce_host_file_open_locked( file_name.data(), file_name.size(), open_flags, lock_type, create_mode, wait_timeout_seconds, - purpose.data(), purpose.size() + purpose.data(), purpose.size(), current.data(), current.size() )); } void file_close_locked(int fd) { uce_host_file_close_locked(fd); } @@ -525,6 +526,7 @@ StringMap default_config() #include #include #include +#include #include "sys.h" #include "hash.h" @@ -793,6 +795,12 @@ bool file_write_all(int fd, const char* data, size_t remaining) { auto bytes_written = write(fd, data, remaining); if(bytes_written < 0) + { + if(errno == EINTR) + continue; + return(false); + } + if(bytes_written == 0) return(false); data += bytes_written; remaining -= bytes_written; @@ -1009,6 +1017,7 @@ u64 socket_connect(String host, short port) { print("SOCKET ERROR (could not connect to address " + String(host) + ":" + std::to_string(port) + ")\n"); perror("SOCKET ERROR "); + close(sockfd); return(0); } context->resources.sockets.push_back(sockfd); diff --git a/src/linux_fastcgi.cpp b/src/linux_fastcgi.cpp index e6710ae..0185ff0 100644 --- a/src/linux_fastcgi.cpp +++ b/src/linux_fastcgi.cpp @@ -851,6 +851,12 @@ static int ws_broker_connect_unix(const String& path) struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; + if(path.size() >= sizeof(addr.sun_path)) + { + fprintf(stderr, "ws broker unix socket path too long: %s\n", path.c_str()); + ::close(fd); + return(-1); + } strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1); if(::connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { @@ -954,7 +960,7 @@ void ws_broker_drain_outbound() ssize_t n = ::send(fd, pending.data(), pending.size(), MSG_NOSIGNAL | MSG_DONTWAIT); if(n > 0) pending.erase(0, n); - else if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + else if(n < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) done = true; } if(!done && pending.empty()) @@ -963,7 +969,7 @@ void ws_broker_drain_outbound() ssize_t r = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT); if(r == 0) done = true; // worker closed the connection: render complete - else if(r < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + else if(r < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) done = true; } if(done) @@ -1279,6 +1285,11 @@ void ensure_proactive_compiler() return; pid_t p = fork(); + if(p < 0) + { + perror("fork proactive compiler"); + return; + } if(p == 0) { file_release_process_locks("proactive compiler fork"); diff --git a/src/wasm/worker.cpp b/src/wasm/worker.cpp index 5595f29..079d5a7 100644 --- a/src/wasm/worker.cpp +++ b/src/wasm/worker.cpp @@ -225,8 +225,12 @@ static bool wasm_read_file(const String& path, std::vector& out) return(false); in.seekg(0, std::ios::end); std::streamoff n = in.tellg(); + if(n < 0) + return(false); in.seekg(0, std::ios::beg); out.resize((size_t)n); + if(n == 0) + return(true); in.read((char*)out.data(), n); return((bool)in); } @@ -473,6 +477,8 @@ public: if(!staged_hostcall_input.empty() && input == staged_hostcall_input) { out = staged_hostcall_result; + staged_hostcall_input = ""; + staged_hostcall_result = ""; return(true); } return(false); @@ -1322,14 +1328,16 @@ private: return(add([self](Caller caller, Span args, Span results) -> Result { String cmd; self->hostcall_read(args[0].i32(), args[1].i32(), cmd); - String out; - if(!self->hostcall_staged("shell:" + cmd, out)) - { - out = ::shell_exec(cmd); - self->hostcall_stage("shell:" + cmd, out); - } u32 cap = (u32)args[3].i32(); int32_t buf = args[2].i32(); + String out; + String stage_key = "shell:" + cmd; + if(!self->hostcall_staged(stage_key, out)) + { + out = ::shell_exec(cmd); + if(buf == 0) + self->hostcall_stage(stage_key, out); + } if(buf != 0 && cap >= out.size()) self->hostcall_write(buf, out); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); @@ -1427,10 +1435,14 @@ private: })); if(mod == "env" && name == "uce_host_file_open_locked") return(add([self](Caller, Span args, Span results) -> Result { - String path, purpose; + String path, purpose, current; self->hostcall_read(args[0].i32(), args[1].i32(), path); self->hostcall_read(args[6].i32(), args[7].i32(), purpose); - int fd = ::file_open_locked(path, args[2].i32(), args[3].i32(), args[4].i32(), args[5].f64(), purpose); + self->hostcall_read(args[8].i32(), args[9].i32(), current); + int open_flags = args[2].i32(); + bool may_write = (open_flags & (O_WRONLY | O_RDWR | O_CREAT | O_TRUNC | O_APPEND)) != 0; + String resolved = may_write ? self->resolve_guest_write(path, current) : self->resolve_guest_file(path, current); + int fd = resolved != "" ? ::file_open_locked(resolved, open_flags, args[3].i32(), args[4].i32(), args[5].f64(), purpose) : -1; int handle = -1; if(fd >= 0) { @@ -1578,8 +1590,11 @@ private: return(add([self](Caller, Span args, Span results) -> Result { String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); + u32 cap = (u32)args[3].i32(); + int32_t buf = args[2].i32(); String out; - if(!self->hostcall_staged(encoded, out)) + String stage_key = "zip:" + encoded; + if(!self->hostcall_staged(stage_key, out)) { DValue request, response; String decode_error; @@ -1625,10 +1640,9 @@ private: response["error"] = e.what(); } out = ucb_encode(response); - self->hostcall_stage(encoded, out); + if(buf == 0) + self->hostcall_stage(stage_key, out); } - u32 cap = (u32)args[3].i32(); - int32_t buf = args[2].i32(); if(buf != 0 && cap >= out.size()) self->hostcall_write(buf, out); results[0] = Val((int32_t)out.size()); @@ -1638,8 +1652,11 @@ private: return(add([self](Caller caller, Span args, Span results) -> Result { String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); + u32 cap = (u32)args[3].i32(); + int32_t buf = args[2].i32(); String out; - if(!self->hostcall_staged(encoded, out)) + String stage_key = "units:" + encoded; + if(!self->hostcall_staged(stage_key, out)) { DValue request, response; String decode_error; @@ -1678,10 +1695,9 @@ private: response["error"] = e.what(); } out = ucb_encode(response); - self->hostcall_stage(encoded, out); + if(buf == 0) + self->hostcall_stage(stage_key, out); } - u32 cap = (u32)args[3].i32(); - int32_t buf = args[2].i32(); if(buf != 0 && cap >= out.size()) self->hostcall_write(buf, out); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); @@ -1696,9 +1712,12 @@ private: // handle table (handle = 1-based index). String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); + u32 cap = (u32)args[3].i32(); + int32_t buf = args[2].i32(); String out; + String stage_key = "sqlite:" + encoded; // run the op once across the length-query + fetch pair - if(!self->hostcall_staged(encoded, out)) + if(!self->hostcall_staged(stage_key, out)) { DValue request, response; String decode_error; @@ -1746,10 +1765,9 @@ private: } } out = ucb_encode(response); - self->hostcall_stage(encoded, out); + if(buf == 0) + self->hostcall_stage(stage_key, out); } - u32 cap = (u32)args[3].i32(); - int32_t buf = args[2].i32(); if(buf != 0 && cap >= out.size()) self->hostcall_write(buf, out); results[0] = Val((int32_t)out.size()); @@ -1789,8 +1807,11 @@ private: return(add([self](Caller, Span args, Span results) -> Result { String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); + u32 cap = (u32)args[3].i32(); + int32_t buf = args[2].i32(); String out; - if(!self->hostcall_staged(encoded, out)) + String stage_key = "mysql:" + encoded; + if(!self->hostcall_staged(stage_key, out)) { DValue request, response; String decode_error; @@ -1839,10 +1860,9 @@ private: } } out = ucb_encode(response); - self->hostcall_stage(encoded, out); + if(buf == 0) + self->hostcall_stage(stage_key, out); } - u32 cap = (u32)args[3].i32(); - int32_t buf = args[2].i32(); if(buf != 0 && cap >= out.size()) self->hostcall_write(buf, out); results[0] = Val((int32_t)out.size());