int socket::connect_sock(const std::string& host, uint16_t port) { int sock; NO_INTR(sock, ::socket(PF_INET, SOCK_STREAM, 0)); if (FAILED(sock)){ return -1; } int res; std::vector<ipv4_address> ips = resolve(host, port); for (int i=0; i < (int)ips.size(); i++){ sockaddr_in addrin={}; addrin.sin_family = PF_INET; addrin.sin_addr.s_addr = inet_addr(ips[i].to_string().c_str()); addrin.sin_port = htons(port); NO_INTR(res,::connect(sock,(sockaddr*)&addrin,sizeof(addrin))); if (SUCCEEDED(res)) { return sock; } } NO_INTR(res, ::close(sock)); return -1; }
bool socket::set_nodelay_sock(int sock, bool on) { if(sock < 0) { return false; } #ifdef __linux__ int n=on?1:0; int res; NO_INTR(res,setsockopt(sock,SOL_TCP,TCP_NODELAY,&n,sizeof(n))); if (FAILED(res)) return false; NO_INTR(res,setsockopt(sock,SOL_SOCKET,TCP_DEFER_ACCEPT,&n,sizeof(n))); return SUCCEEDED(res); #else return true; #endif }
bool KPtyDevicePrivate::_k_canWrite() { Q_Q(KPtyDevice); writeNotifier->setEnabled(false); if (writeBuffer.isEmpty()) return false; qt_ignore_sigpipe(); int wroteBytes; NO_INTR(wroteBytes, write(q->masterFd(), writeBuffer.readPointer(), writeBuffer.readSize())); if (wroteBytes < 0) { q->setErrorString(QLatin1String("Error writing to PTY")); return false; } writeBuffer.free(wroteBytes); if (!emittedBytesWritten) { emittedBytesWritten = true; emit q->bytesWritten(wroteBytes); emittedBytesWritten = false; } if (!writeBuffer.isEmpty()) writeNotifier->setEnabled(true); return true; }
static int safe_read (int fd, gchar *buffer, gint count, GError **error) { int res; NO_INTR (res, read (fd, buffer, count)); set_error_cond (res == -1, "%s", "Error reading from pipe."); return res; }
int mmapper::open(const string& filename){ int r; close(); NO_INTR(fd, ::open(filename.c_str(), O_RDWR)); if (FAILED(fd)) return -1; struct stat st_buf; NO_INTR(r, fstat(fd, &st_buf)); if (FAILED(fd)) { close(); return -1; } length = st_buf.st_size; int prot = PROT_WRITE | PROT_READ; void *p = NULL; NO_INTR(p, mmap(NULL, length, prot, MAP_SHARED, fd, 0)); if (p == MAP_FAILED) { close(); return -1; } ptr = (char*)p; return 0; }
int socket::listen_sock(uint16_t port, int backlog) { int res; int sock; NO_INTR(sock, ::socket(PF_INET, SOCK_STREAM, 0)); if (FAILED(sock)) { return -1; } int yes = 1; NO_INTR(res, ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes))); if (FAILED(res)){ NO_INTR(res, ::close(sock)); return -1; } sockaddr_in saddr = {}; saddr.sin_family = PF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(port); NO_INTR(res, ::bind(sock, (sockaddr*)&saddr, sizeof(saddr))); if (FAILED(res)){ NO_INTR(res, ::close(sock)); return -1; } linger ling={0,0}; NO_INTR(res, ::setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling))); if (FAILED(res)){ NO_INTR(res, ::close(sock)); return -1; } NO_INTR(res, ::listen(sock, backlog)); if (FAILED(res)){ NO_INTR(res, ::close(sock)); return -1; } return sock; }
bool socket::set_timeout_sockopt(int sock, int optname, double sec) { if(sock < 0) { return false; } timeval tv; tv.tv_sec = std::max(0,(int)sec); tv.tv_usec = std::min(999999, std::max(0,(int)((sec-tv.tv_sec)*1e6))); int res; NO_INTR(res,setsockopt(sock,SOL_SOCKET,optname,&tv,sizeof(tv))); return SUCCEEDED(res); }
_END_GOOGLE_NAMESPACE_ #if defined(__ELF__) #include <dlfcn.h> #include <elf.h> #include <errno.h> #include <fcntl.h> #include <limits.h> #include <link.h> // For ElfW() macro. #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include "symbolize.h" #include "gconfig.h" // Re-runs fn until it doesn't cause EINTR. #define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) _START_GOOGLE_NAMESPACE_ // Read up to "count" bytes from file descriptor "fd" into the buffer // starting at "buf" while handling short reads and EINTR. On // success, return the number of bytes read. Otherwise, return -1. static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) { SAFE_ASSERT(fd >= 0); SAFE_ASSERT(count <= SSIZE_MAX); char *buf0 = reinterpret_cast<char *>(buf); size_t num_bytes = 0; while (num_bytes < count) { ssize_t len; NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes)); if (len < 0) { // There was an error other than EINTR. return -1; } if (len == 0) { // Reached EOF. break; } num_bytes += len; } SAFE_ASSERT(num_bytes <= count); return num_bytes; }
/* Signal handler to help us recover from dying while we are attached to * other threads. */ static void SignalHandler(int signum, siginfo_t *si, void *data) { if (sig_pids != NULL) { if (signum == SIGABRT) { while (sig_num_threads-- > 0) { /* Not sure if sched_yield is really necessary here, but it does not */ /* hurt, and it might be necessary for the same reasons that we have */ /* to do so in sys_ptrace_detach(). */ sys_sched_yield(); sys_ptrace(PTRACE_KILL, sig_pids[sig_num_threads], 0, 0); } } else if (sig_num_threads > 0) { ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids); } } sig_pids = NULL; if (sig_marker >= 0) NO_INTR(sys_close(sig_marker)); sig_marker = -1; if (sig_proc >= 0) NO_INTR(sys_close(sig_proc)); sig_proc = -1; sys__exit(signum == SIGABRT ? 1 : 2); }
/* * This is the only use we have in mono/metadata !g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, &ch_in, &ch_out, NULL, NULL) */ gboolean g_spawn_async_with_pipes (const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid, gint *standard_input, gint *standard_output, gint *standard_error, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; int info_pipe [2]; int in_pipe [2] = { -1, -1 }; int out_pipe [2] = { -1, -1 }; int err_pipe [2] = { -1, -1 }; int status; g_return_val_if_fail (argv != NULL, FALSE); /* Only mandatory arg */ if (!create_pipe (info_pipe, error)) return FALSE; if (standard_output && !create_pipe (out_pipe, error)) { CLOSE_PIPE (info_pipe); return FALSE; } if (standard_error && !create_pipe (err_pipe, error)) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); return FALSE; } if (standard_input && !create_pipe (in_pipe, error)) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); return FALSE; } pid = fork (); if (pid == -1) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); CLOSE_PIPE (in_pipe); set_error ("%s", "Error in fork ()"); return FALSE; } if (pid == 0) { /* No zombie left behind */ if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { pid = fork (); } if (pid != 0) { exit (pid == -1 ? 1 : 0); } else { gint i; int fd; gchar *arg0; gchar **actual_args; gint unused; close (info_pipe [0]); close (in_pipe [1]); close (out_pipe [0]); close (err_pipe [0]); /* when exec* succeeds, we want to close this fd, which will return * a 0 read on the parent. We're not supposed to keep it open forever. * If exec fails, we still can write the error to it before closing. */ fcntl (info_pipe [1], F_SETFD, FD_CLOEXEC); if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { pid = getpid (); NO_INTR (unused, write_all (info_pipe [1], &pid, sizeof (pid_t))); } if (working_directory && chdir (working_directory) == -1) { int err = errno; NO_INTR (unused, write_all (info_pipe [1], &err, sizeof (int))); exit (0); } if (standard_output) { dup2 (out_pipe [1], STDOUT_FILENO); } else if ((flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0) { fd = open ("/dev/null", O_WRONLY); dup2 (fd, STDOUT_FILENO); } if (standard_error) { dup2 (err_pipe [1], STDERR_FILENO); } else if ((flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0) { fd = open ("/dev/null", O_WRONLY); dup2 (fd, STDERR_FILENO); } if (standard_input) { dup2 (in_pipe [0], STDIN_FILENO); } else if ((flags & G_SPAWN_CHILD_INHERITS_STDIN) == 0) { fd = open ("/dev/null", O_RDONLY); dup2 (fd, STDIN_FILENO); } if ((flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) != 0) { for (i = getdtablesize () - 1; i >= 3; i--) close (i); } actual_args = ((flags & G_SPAWN_FILE_AND_ARGV_ZERO) == 0) ? argv : argv + 1; if (envp == NULL) envp = environ; if (child_setup) child_setup (user_data); arg0 = argv [0]; if (!g_path_is_absolute (arg0) || (flags & G_SPAWN_SEARCH_PATH) != 0) { arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { int err = ENOENT; write_all (info_pipe [1], &err, sizeof (int)); exit (0); } } execve (arg0, actual_args, envp); write_all (info_pipe [1], &errno, sizeof (int)); exit (0); } } else if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { int w; /* Wait for the first child if two are created */ NO_INTR (w, waitpid (pid, &status, 0)); if (status == 1 || w == -1) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); CLOSE_PIPE (in_pipe); set_error ("Error in fork (): %d", status); return FALSE; } } close (info_pipe [1]); close (in_pipe [0]); close (out_pipe [1]); close (err_pipe [1]); if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { int x; NO_INTR (x, read (info_pipe [0], &pid, sizeof (pid_t))); /* if we read < sizeof (pid_t)... */ } if (child_pid) { *child_pid = pid; } if (read (info_pipe [0], &status, sizeof (int)) != 0) { close (info_pipe [0]); close (in_pipe [0]); close (out_pipe [1]); close (err_pipe [1]); set_error_status (status, "Error in exec (%d -> %s)", status, strerror (status)); return FALSE; } close (info_pipe [0]); if (standard_input) *standard_input = in_pipe [1]; if (standard_output) *standard_output = out_pipe [0]; if (standard_error) *standard_error = err_pipe [0]; #endif return TRUE; }
gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, gint *exit_status, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; gchar **argv; gint argc; int stdout_pipe [2] = { -1, -1 }; int stderr_pipe [2] = { -1, -1 }; int status; int res; if (!g_shell_parse_argv (command_line, &argc, &argv, error)) return FALSE; if (standard_output && !create_pipe (stdout_pipe, error)) return FALSE; if (standard_error && !create_pipe (stderr_pipe, error)) { if (standard_output) { CLOSE_PIPE (stdout_pipe); } return FALSE; } pid = fork (); if (pid == 0) { gint i; if (standard_output) { close (stdout_pipe [0]); dup2 (stdout_pipe [1], STDOUT_FILENO); } if (standard_error) { close (stderr_pipe [0]); dup2 (stderr_pipe [1], STDERR_FILENO); } for (i = getdtablesize () - 1; i >= 3; i--) close (i); /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */ if (!g_path_is_absolute (argv [0])) { gchar *arg0; arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { exit (1); } //g_free (argv [0]); argv [0] = arg0; } execv (argv [0], argv); exit (1); /* TODO: What now? */ } g_strfreev (argv); if (standard_output) close (stdout_pipe [1]); if (standard_error) close (stderr_pipe [1]); if (standard_output || standard_error) { res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, error); if (res) { waitpid (pid, &status, WNOHANG); /* avoid zombie */ return FALSE; } } NO_INTR (res, waitpid (pid, &status, 0)); /* TODO: What if error? */ if (WIFEXITED (status) && exit_status) { *exit_status = WEXITSTATUS (status); } #endif return TRUE; }
static void ListerThread(struct ListerParams *args) { int found_parent = 0; pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); char proc_self_task[80], marker_name[48], *marker_path; const char *proc_paths[3]; const char *const *proc_path = proc_paths; int proc = -1, marker = -1, num_threads = 0; int max_threads = 0, sig; struct kernel_stat marker_sb, proc_sb; stack_t altstack; /* Create "marker" that we can use to detect threads sharing the same * address space and the same file handles. By setting the FD_CLOEXEC flag * we minimize the risk of misidentifying child processes as threads; * and since there is still a race condition, we will filter those out * later, anyway. */ if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { failure: args->result = -1; args->err = errno; if (marker >= 0) NO_INTR(sys_close(marker)); sig_marker = marker = -1; if (proc >= 0) NO_INTR(sys_close(proc)); sig_proc = proc = -1; sys__exit(1); } /* Compute search paths for finding thread directories in /proc */ local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); strcpy(marker_name, proc_self_task); marker_path = marker_name + strlen(marker_name); strcat(proc_self_task, "/task/"); proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ proc_paths[1] = "/proc/"; /* /proc/ */ proc_paths[2] = NULL; /* Compute path for marker socket in /proc */ local_itoa(strcpy(marker_path, "/fd/") + 4, marker); if (sys_stat(marker_name, &marker_sb) < 0) { goto failure; } /* Catch signals on an alternate pre-allocated stack. This way, we can * safely execute the signal handler even if we ran out of memory. */ memset(&altstack, 0, sizeof(altstack)); altstack.ss_sp = args->altstack_mem; altstack.ss_flags = 0; altstack.ss_size = ALT_STACKSIZE; sys_sigaltstack(&altstack, (const stack_t *)NULL); /* Some kernels forget to wake up traced processes, when the * tracer dies. So, intercept synchronous signals and make sure * that we wake up our tracees before dying. It is the caller's * responsibility to ensure that asynchronous signals do not * interfere with this function. */ sig_marker = marker; sig_proc = -1; for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { struct kernel_sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction_ = SignalHandler; sys_sigfillset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); } /* Read process directories in /proc/... */ for (;;) { /* Some kernels know about threads, and hide them in "/proc" * (although they are still there, if you know the process * id). Threads are moved into a separate "task" directory. We * check there first, and then fall back on the older naming * convention if necessary. */ if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { if (*++proc_path != NULL) continue; goto failure; } if (sys_fstat(proc, &proc_sb) < 0) goto failure; /* Since we are suspending threads, we cannot call any libc * functions that might acquire locks. Most notably, we cannot * call malloc(). So, we have to allocate memory on the stack, * instead. Since we do not know how much memory we need, we * make a best guess. And if we guessed incorrectly we retry on * a second iteration (by jumping to "detach_threads"). * * Unless the number of threads is increasing very rapidly, we * should never need to do so, though, as our guestimate is very * conservative. */ if (max_threads < proc_sb.st_nlink + 100) max_threads = proc_sb.st_nlink + 100; /* scope */ { pid_t pids[max_threads]; int added_entries = 0; sig_num_threads = num_threads; sig_pids = pids; for (;;) { struct kernel_dirent *entry; char buf[4096]; ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, sizeof(buf)); if (nbytes < 0) goto failure; else if (nbytes == 0) { if (added_entries) { /* Need to keep iterating over "/proc" in multiple * passes until we no longer find any more threads. This * algorithm eventually completes, when all threads have * been suspended. */ added_entries = 0; sys_lseek(proc, 0, SEEK_SET); continue; } break; } for (entry = (struct kernel_dirent *)buf; entry < (struct kernel_dirent *)&buf[nbytes]; entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { if (entry->d_ino != 0) { const char *ptr = entry->d_name; pid_t pid; /* Some kernels hide threads by preceding the pid with a '.' */ if (*ptr == '.') ptr++; /* If the directory is not numeric, it cannot be a * process/thread */ if (*ptr < '0' || *ptr > '9') continue; pid = local_atoi(ptr); /* Attach (and suspend) all threads */ if (pid && pid != clone_pid) { struct kernel_stat tmp_sb; char fname[entry->d_reclen + 48]; strcat(strcat(strcpy(fname, "/proc/"), entry->d_name), marker_path); /* Check if the marker is identical to the one we created */ if (sys_stat(fname, &tmp_sb) >= 0 && marker_sb.st_ino == tmp_sb.st_ino) { long i, j; /* Found one of our threads, make sure it is no duplicate */ for (i = 0; i < num_threads; i++) { /* Linear search is slow, but should not matter much for * the typically small number of threads. */ if (pids[i] == pid) { /* Found a duplicate; most likely on second pass */ goto next_entry; } } /* Check whether data structure needs growing */ if (num_threads >= max_threads) { /* Back to square one, this time with more memory */ NO_INTR(sys_close(proc)); goto detach_threads; } /* Attaching to thread suspends it */ pids[num_threads++] = pid; sig_num_threads = num_threads; if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, (void *)0) < 0) { /* If operation failed, ignore thread. Maybe it * just died? There might also be a race * condition with a concurrent core dumper or * with a debugger. In that case, we will just * make a best effort, rather than failing * entirely. */ num_threads--; sig_num_threads = num_threads; goto next_entry; } while (sys_waitpid(pid, (int *)0, __WALL) < 0) { if (errno != EINTR) { sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; goto next_entry; } } if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { /* Address spaces are distinct, even though both * processes show the "marker". This is probably * a forked child process rather than a thread. */ sys_ptrace_detach(pid); num_threads--; sig_num_threads = num_threads; } else { found_parent |= pid == ppid; added_entries++; } } } } next_entry:; } } NO_INTR(sys_close(proc)); sig_proc = proc = -1; /* If we failed to find any threads, try looking somewhere else in * /proc. Maybe, threads are reported differently on this system. */ if (num_threads > 1 || !*++proc_path) { NO_INTR(sys_close(marker)); sig_marker = marker = -1; /* If we never found the parent process, something is very wrong. * Most likely, we are running in debugger. Any attempt to operate * on the threads would be very incomplete. Let's just report an * error to the caller. */ if (!found_parent) { ResumeAllProcessThreads(num_threads, pids); sys__exit(3); } /* Now we are ready to call the callback, * which takes care of resuming the threads for us. */ args->result = args->callback(args->parameter, num_threads, pids, args->ap); args->err = errno; /* Callback should have resumed threads, but better safe than sorry */ if (ResumeAllProcessThreads(num_threads, pids)) { /* Callback forgot to resume at least one thread, report error */ args->err = EINVAL; args->result = -1; } sys__exit(0); } detach_threads: /* Resume all threads prior to retrying the operation */ ResumeAllProcessThreads(num_threads, pids); sig_pids = NULL; num_threads = 0; sig_num_threads = num_threads; max_threads += 100; } } }
/* Wrapper for open() which is guaranteed to never return EINTR. */ static int c_open(const char *fname, int flags, int mode) { ssize_t rc; NO_INTR(rc = sys_open(fname, flags, mode)); return rc; }
bool KPtyDevicePrivate::_k_canRead() { Q_Q(KPtyDevice); qint64 readBytes = 0; #ifdef Q_OS_IRIX // this should use a config define, but how to check it? size_t available; #else int available; #endif if (!::ioctl(q->masterFd(), PTY_BYTES_AVAILABLE, (char *) &available)) { #ifdef Q_OS_SOLARIS // A Pty is a STREAMS module, and those can be activated // with 0 bytes available. This happens either when ^C is // pressed, or when an application does an explicit write(a,b,0) // which happens in experiments fairly often. When 0 bytes are // available, you must read those 0 bytes to clear the STREAMS // module, but we don't want to hit the !readBytes case further down. if (!available) { char c; // Read the 0-byte STREAMS message NO_INTR(readBytes, read(q->masterFd(), &c, 0)); // Should return 0 bytes read; -1 is error if (readBytes < 0) { readNotifier->setEnabled(false); emit q->readEof(); return false; } return true; } #endif char *ptr = readBuffer.reserve(available); #ifdef Q_OS_SOLARIS // Even if available > 0, it is possible for read() // to return 0 on Solaris, due to 0-byte writes in the stream. // Ignore them and keep reading until we hit *some* data. // In Solaris it is possible to have 15 bytes available // and to (say) get 0, 0, 6, 0 and 9 bytes in subsequent reads. // Because the stream is set to O_NONBLOCK in finishOpen(), // an EOF read will return -1. readBytes = 0; while (!readBytes) #endif // Useless block braces except in Solaris { NO_INTR(readBytes, read(q->masterFd(), ptr, available)); } if (readBytes < 0) { readBuffer.unreserve(available); q->setErrorString(QLatin1String("Error reading from PTY")); return false; } readBuffer.unreserve(available - readBytes); // *should* be a no-op } if (!readBytes) { readNotifier->setEnabled(false); emit q->readEof(); return false; } else { if (!emittedReadyRead) { emittedReadyRead = true; emit q->readyRead(); emittedReadyRead = false; } return true; } }