size_t ModuleList::RemoveOrphans (bool mandatory) { Mutex::Locker locker; if (mandatory) { locker.Lock (m_modules_mutex); } else { // Not mandatory, remove orphans if we can get the mutex if (!locker.TryLock(m_modules_mutex)) return 0; } collection::iterator pos = m_modules.begin(); size_t remove_count = 0; while (pos != m_modules.end()) { if (pos->unique()) { pos = RemoveImpl(pos); ++remove_count; } else { ++pos; } } return remove_count; }
ConnectionStatus ConnectionFileDescriptor::Disconnect (Error *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void*>(this)); ConnectionStatus status = eConnectionStatusSuccess; if (!IsConnected()) { if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void*>(this)); return eConnectionStatusSuccess; } if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) static_cast<Socket&>(*m_read_sp).PreDisconnect(); // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely // because somebody is doing a blocking read on our file descriptor. If that's the case, // then send the "q" char to the command file channel so the read will wake up and the connection // will then know to shut down. m_shutting_down = true; Mutex::Locker locker; bool got_lock = locker.TryLock (m_mutex); if (!got_lock) { if (m_pipe.WriteDescriptorIsValid()) { int result; result = m_pipe.Write("q", 1) == 1; if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.", static_cast<void*>(this), m_pipe.GetWriteFileDescriptor(), result); } else if (log) { log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", static_cast<void*>(this)); } locker.Lock (m_mutex); } Error error = m_read_sp->Close(); Error error2 = m_write_sp->Close(); if (error.Fail() || error2.Fail()) status = eConnectionStatusError; if (error_ptr) *error_ptr = error.Fail() ? error : error2; m_shutting_down = false; return status; }
bool GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message) { if (IsRunning()) return locker.TryLock (m_sequence_mutex, failure_message); locker.Lock (m_sequence_mutex); return true; }
size_t ConnectionFileDescriptor::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) { LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %llu)...", this, m_fd_recv, dst, (uint64_t)dst_len); Mutex::Locker locker; bool got_lock = locker.TryLock (m_mutex); if (!got_lock) { if (log) log->Printf ("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", this); if (error_ptr) error_ptr->SetErrorString ("failed to get the connection lock for read."); status = eConnectionStatusTimedOut; return 0; } else if (m_shutting_down) return eConnectionStatusError; ssize_t bytes_read = 0; status = BytesAvailable (timeout_usec, error_ptr); if (status == eConnectionStatusSuccess) { do { bytes_read = ::read (m_fd_recv, dst, dst_len); } while (bytes_read < 0 && errno == EINTR); } if (status != eConnectionStatusSuccess) return 0; Error error; if (bytes_read == 0) { error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. status = eConnectionStatusEndOfFile; } else if (bytes_read < 0) { error.SetErrorToErrno(); } else { error.Clear(); } if (log) log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %llu) => %lli, error = %s", this, m_fd_recv, dst, (uint64_t)dst_len, (int64_t)bytes_read, error.AsCString()); if (error_ptr) *error_ptr = error; if (error.Fail()) { uint32_t error_value = error.GetError(); switch (error_value) { case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. if (m_fd_recv_type == eFDTypeSocket || m_fd_recv_type == eFDTypeSocketUDP) status = eConnectionStatusTimedOut; else status = eConnectionStatusSuccess; return 0; case EFAULT: // Buf points outside the allocated address space. case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. case EINVAL: // The pointer associated with fildes was negative. case EIO: // An I/O error occurred while reading from the file system. // The process group is orphaned. // The file is a regular file, nbyte is greater than 0, // the starting position is before the end-of-file, and // the starting position is greater than or equal to the // offset maximum established for the open file // descriptor associated with fildes. case EISDIR: // An attempt is made to read a directory. case ENOBUFS: // An attempt to allocate a memory buffer fails. case ENOMEM: // Insufficient memory is available. status = eConnectionStatusError; break; // Break to close.... case ENOENT: // no such file or directory case EBADF: // fildes is not a valid file or socket descriptor open for reading. case ENXIO: // An action is requested of a device that does not exist.. // A requested action cannot be performed by the device. case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket. case ENOTCONN: // A read is attempted on an unconnected socket. status = eConnectionStatusLostConnection; break; // Break to close.... case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. status = eConnectionStatusTimedOut; return 0; } //Disconnect (NULL); return 0; } return bytes_read; }
ConnectionStatus ConnectionFileDescriptor::Disconnect (Error *error_ptr) { LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this); ConnectionStatus status = eConnectionStatusSuccess; if (m_fd_send < 0 && m_fd_recv < 0) { if (log) log->Printf ("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", this); return eConnectionStatusSuccess; } // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely // because somebody is doing a blocking read on our file descriptor. If that's the case, // then send the "q" char to the command file channel so the read will wake up and the connection // will then know to shut down. m_shutting_down = true; Mutex::Locker locker; bool got_lock= locker.TryLock (m_mutex); if (!got_lock) { if (m_pipe_write != -1 ) { write (m_pipe_write, "q", 1); close (m_pipe_write); m_pipe_write = -1; } locker.Lock (m_mutex); } if (m_should_close_fd == true) { if (m_fd_send == m_fd_recv) { status = Close (m_fd_send, error_ptr); } else { // File descriptors are the different, close both if needed if (m_fd_send >= 0) status = Close (m_fd_send, error_ptr); if (m_fd_recv >= 0) { ConnectionStatus recv_status = Close (m_fd_recv, error_ptr); if (status == eConnectionStatusSuccess) status = recv_status; } } } // Now set all our descriptors to invalid values. m_fd_send = m_fd_recv = -1; if (status != eConnectionStatusSuccess) { return status; } m_shutting_down = false; return eConnectionStatusSuccess; }
bool CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker) { return locker.TryLock (m_sequence_mutex); }