diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 19:00:58 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 19:00:58 +0000 |
commit | cd3cf12588560bf1c1ffc780ce7fdeae044b100e (patch) | |
tree | 8ab79805aa9e50db3a2eae36e324af2f92bc13d4 /base/dir_reader_linux.h | |
parent | 2fc4c21d0b6cebaf8ebc101cc3fe20ef38407373 (diff) | |
download | chromium_src-cd3cf12588560bf1c1ffc780ce7fdeae044b100e.zip chromium_src-cd3cf12588560bf1c1ffc780ce7fdeae044b100e.tar.gz chromium_src-cd3cf12588560bf1c1ffc780ce7fdeae044b100e.tar.bz2 |
POSIX: don't allocate memory after forking.
Previously we would allocate memory in the child process. However, the
allocation might have happened while the malloc lock was held,
resulting in a deadlock.
This patch removes allocation from the child but probably makes Mac's
startup time slower until a Mac person can implement
dir_reader_posix.h.
TEST=Unittest for new code
BUG=36678
http://codereview.chromium.org/672003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41181 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/dir_reader_linux.h')
-rw-r--r-- | base/dir_reader_linux.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/base/dir_reader_linux.h b/base/dir_reader_linux.h new file mode 100644 index 0000000..7fd534f --- /dev/null +++ b/base/dir_reader_linux.h @@ -0,0 +1,97 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_DIR_READER_LINUX_H_ +#define BASE_DIR_READER_LINUX_H_ + +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/syscall.h> +#include <unistd.h> + +#include "base/logging.h" +#include "base/eintr_wrapper.h" + +// See the comments in dir_reader_posix.h about this. + +namespace base { + +struct linux_dirent { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[0]; +}; + +class DirReaderLinux { + public: + explicit DirReaderLinux(const char* directory_path) + : fd_(open(directory_path, O_RDONLY | O_DIRECTORY)), + offset_(0), + size_(0) { + } + + ~DirReaderLinux() { + if (fd_ >= 0) { + if (HANDLE_EINTR(close(fd_))) + RAW_LOG(ERROR, "Failed to close directory handle"); + } + } + + bool IsValid() const { + return fd_ >= 0; + } + + // Move to the next entry returning false if the iteration is complete. + bool Next() { + if (size_) { + linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]); + offset_ += dirent->d_reclen; + } + + if (offset_ != size_) + return true; + + const int r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_)); + if (r == 0) + return false; + if (r == -1) { + DPLOG(FATAL) << "getdents64 returned an error: " << errno; + return false; + } + size_ = r; + offset_ = 0; + return true; + } + + const char* name() const { + if (!size_) + return NULL; + + const linux_dirent* dirent = + reinterpret_cast<const linux_dirent*>(&buf_[offset_]); + return dirent->d_name; + } + + int fd() const { + return fd_; + } + + static bool IsFallback() { + return false; + } + + private: + const int fd_; + unsigned char buf_[512]; + size_t offset_, size_; + + DISALLOW_COPY_AND_ASSIGN(DirReaderLinux); +}; + +} // namespace base + +#endif // BASE_DIR_READER_LINUX_H_ |