static void node_thread(void *dummy) { while (!node_shut_down) { node_launch(); fprintf(stderr, "app: Node launched, sending init.\n"); invoke_on_main_thread(node_send_init, NULL); time_t startTime = time(NULL); char buf[10240]; while (1) { DWORD cb = 0; BOOL success = ReadFile(node_stdout_fd, buf, sizeof(buf), &cb, NULL); if (!success) break; if (cb == 0) break; // end of file node_received_raw(buf, cb); } if (!node_shut_down) { CloseHandle(node_stdin_fd); CloseHandle(node_stdout_fd); DWORD result = WaitForSingleObject(node_process, 2000); if (result != WAIT_OBJECT_0) { TerminateProcess(node_process, 42); } CloseHandle(node_process); } time_t endTime = time(NULL); if (endTime < startTime + 3) { // shut down in less than 3 seconds considered a crash node_shut_down = true; invoke_on_main_thread(node_emergency_shutdown, NULL); } fprintf(stderr, "app: Node terminated.\n"); } }
static void fsmonitor_callback(fsdiff_t *diff, void *data) { item_t *item = (item_t *)data; json_t *json = json_array(); int count = fsdiff_count(diff); for (int i = 0; i < count; ++i) json_array_append(json, json_string(fsdiff_get(diff, i))); fsdiff_free(diff); change_t *change = (change_t *)malloc(sizeof(change_t)); change->id = json_incref(item->id); change->diff = json; invoke_on_main_thread(fsmonitor_callback_main_thread, change); }
void node_received_raw(char *buf, int cb) { strncat(node_buf, buf, cb); char *start = buf; char *end; while ((end = (char *)strchr(start, '\n')) != NULL) { *end = 0; invoke_on_main_thread((INVOKE_LATER_FUNC)node_received, strdup(start)); start = end + 1; } if (start > buf) { // strings overlap, so can't use strcpy memmove(buf, start, strlen(start) + 1); } }
void do_listen(fsmonitor_t *monitor) { HANDLE hChange = FindFirstChangeNotification(U2W(monitor->path), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES); assert(hChange != INVALID_HANDLE_VALUE); printf("Listening to changes in %s\n", monitor->path); while (TRUE) { DWORD status = WaitForMultipleObjects(1, &hChange, FALSE, INFINITE); if (status == WAIT_OBJECT_0) { printf("Detected change in %s\n", monitor->path); invoke_on_main_thread((INVOKE_LATER_FUNC) fsmonitor_did_detect_change, monitor); DWORD result = FindNextChangeNotification(hChange); assert(result); } else { assert(!"WaitForMultipleObjects returned error"); } } }
static void *node_thread(void *dummy) { int pipe_stdin[2], pipe_stdout[2]; int result; restart_node: result = pipe(pipe_stdin); assert(result == 0); result = pipe(pipe_stdout); assert(result == 0); int pid = fork(); assert(pid >= 0); if (pid == 0) { if (pipe_stdin[0] != STDIN_FILENO) { dup2(pipe_stdin[0], STDIN_FILENO); close(pipe_stdin[0]); } close(pipe_stdin[1]); if (pipe_stdout[1] != STDOUT_FILENO) { dup2(pipe_stdout[1], STDOUT_FILENO); close(pipe_stdout[1]); } close(pipe_stdout[0]); write(STDOUT_FILENO, "Hello!\n", strlen("Hello!\n")); execl(os_bundled_node_path, "node", node_bundled_backend_js, NULL); _exit(127); } node_pid = pid; invoke_on_main_thread(node_send_init, NULL); close(pipe_stdin[0]); node_stdin_fd = pipe_stdin[1]; close(pipe_stdout[1]); node_stdout_fd = pipe_stdout[0]; // cool! now time to actually do something... fd_set pristine_read_fds, read_fds; FD_ZERO(&pristine_read_fds); FD_SET(node_stdout_fd, &pristine_read_fds); int max_fd = node_stdout_fd + 1; char buf[10240]; while (1) { int rv; do { read_fds = pristine_read_fds; rv = select(max_fd, &read_fds, NULL, NULL, NULL); } while (rv == EINTR); if (rv < 0) { perror("select"); assert(0); } if (FD_ISSET(node_stdout_fd, &read_fds)) { int cb = read(node_stdout_fd, buf, sizeof(buf)); if (cb <= 0) { break; } node_received_raw(buf, cb); } } int exit_status, rv; do { rv = waitpid(pid, &exit_status, 0); } while (rv == -1 && errno == EINTR); close(node_stdin_fd); close(node_stdout_fd); goto restart_node; }