diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-01 21:37:31 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-01 21:37:31 +0000 |
commit | 157c61b07b3ce5e308db6230da9d93ff74a16ca3 (patch) | |
tree | 7a627dd3c11b684852e2a3ffe84bcfc079bf1316 /base/directory_watcher_inotify.cc | |
parent | 105414ec43286c5ba9953eaf66f147a9a1a6afd5 (diff) | |
download | chromium_src-157c61b07b3ce5e308db6230da9d93ff74a16ca3.zip chromium_src-157c61b07b3ce5e308db6230da9d93ff74a16ca3.tar.gz chromium_src-157c61b07b3ce5e308db6230da9d93ff74a16ca3.tar.bz2 |
POSIX: Add a macro for handling EINTR.
On POSIX systems, system calls can be interrupted by signals. In this
case, they'll return EINTR, indicating that the system call needs to
be restarted.
(The situation is a little more complicated than this with SA_RESTART,
but you can read man 7 signal if you like.)
The short of it is that you need to catch EINTR and restart the call
for these system calls:
* read, readv, write, writev, ioctl
* open() when dealing with a fifo
* wait*
* Anything socket based (send*, recv*, connect, accept etc)
* flock and lock control with fcntl
* mq_ functions which can block
* futex
* sem_wait (and timed wait)
* pause, sigsuspend, sigtimedwait, sigwaitinfo
* poll, epoll_wait, select and 'p' versions of the same
* msgrcv, msgsnd, semop, semtimedop
* close (although, on Linux, EINTR won't happen here)
* any sleep functions (careful, you need to handle this are restart
with different arguments)
We've been a little sloppy with this until now. This patch adds a
macro for dealing with this and corrects every case of these system
calls (that I found).
The macro is HANDLE_EINTR in base/eintr_wrapper.h. It's safe to
include on Windows and is a no-op there.
On POSIX, it uses GCC magic to return the correct type based on the
expression and restarts the system call if it throws EINTR.
And you can use it like:
HANDLE_EINTR(close(fd));
Or:
ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer, len));
*BEWARE* that it will evaluate the argument multiple times, so this is
not safe:
HANDLE_EINTR(close(FireMissiles()));
http://groups.google.com/group/chromium-dev/browse_thread/thread/41a35b2a457d73a0
http://codereview.chromium.org/100225
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15102 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/directory_watcher_inotify.cc')
-rw-r--r-- | base/directory_watcher_inotify.cc | 24 |
1 files changed, 9 insertions, 15 deletions
diff --git a/base/directory_watcher_inotify.cc b/base/directory_watcher_inotify.cc index a17e1e4..86e7bd9 100644 --- a/base/directory_watcher_inotify.cc +++ b/base/directory_watcher_inotify.cc @@ -16,6 +16,7 @@ #include <utility> #include <vector> +#include "base/eintr_wrapper.h" #include "base/file_path.h" #include "base/hash_tables.h" #include "base/lock.h" @@ -100,11 +101,10 @@ class InotifyReaderTask : public Task { FD_SET(shutdown_fd_, &rfds); // Wait until some inotify events are available. - int select_result = select(std::max(inotify_fd_, shutdown_fd_) + 1, - &rfds, NULL, NULL, NULL); + int select_result = + HANDLE_EINTR(select(std::max(inotify_fd_, shutdown_fd_) + 1, + &rfds, NULL, NULL, NULL)); if (select_result < 0) { - if (errno == EINTR) - continue; DLOG(WARNING) << "select failed: " << strerror(errno); return; } @@ -114,7 +114,8 @@ class InotifyReaderTask : public Task { // Adjust buffer size to current event queue size. int buffer_size; - int ioctl_result = ioctl(inotify_fd_, FIONREAD, &buffer_size); + int ioctl_result = HANDLE_EINTR(ioctl(inotify_fd_, FIONREAD, + &buffer_size)); if (ioctl_result != 0) { DLOG(WARNING) << "ioctl failed: " << strerror(errno); @@ -123,10 +124,8 @@ class InotifyReaderTask : public Task { std::vector<char> buffer(buffer_size); - ssize_t bytes_read; - do { - bytes_read = read(inotify_fd_, &buffer[0], buffer_size); - } while (bytes_read < 0 && errno == EINTR); + ssize_t bytes_read = HANDLE_EINTR(read(inotify_fd_, &buffer[0], + buffer_size)); if (bytes_read < 0) { DLOG(WARNING) << "read from inotify fd failed: " << strerror(errno); @@ -188,12 +187,7 @@ InotifyReader::~InotifyReader() { if (valid_) { // Write to the self-pipe so that the select call in InotifyReaderTask // returns. - ssize_t bytes_written; - do { - bytes_written = write(shutdown_pipe_[1], "", 1); - if (bytes_written == 0) - continue; - } while (bytes_written == -1 && errno == EINTR); + HANDLE_EINTR(write(shutdown_pipe_[1], "", 1)); thread_.Stop(); } if (inotify_fd_ >= 0) |