SOURCES: libtorrent-bug-1497.patch (NEW) - fix from trac
arekm
arekm at pld-linux.org
Tue Oct 14 10:09:28 CEST 2008
Author: arekm Date: Tue Oct 14 08:09:28 2008 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- fix from trac
---- Files affected:
SOURCES:
libtorrent-bug-1497.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/libtorrent-bug-1497.patch
diff -u /dev/null SOURCES/libtorrent-bug-1497.patch:1.1
--- /dev/null Tue Oct 14 10:09:29 2008
+++ SOURCES/libtorrent-bug-1497.patch Tue Oct 14 10:09:22 2008
@@ -0,0 +1,197 @@
+# Changes epoll/kqueue to operate by file descriptors, not
+# event pointers, to hopefully fix the recent poll crashes.
+Index: libtorrent/src/torrent/poll_epoll.cc
+===================================================================
+--- libtorrent/src/torrent/poll_epoll.cc (revision 1072)
++++ libtorrent/src/torrent/poll_epoll.cc (working copy)
+@@ -60,7 +60,7 @@
+
+ inline void
+ PollEPoll::set_event_mask(Event* e, uint32_t m) {
+- m_table[e->file_descriptor()] = std::make_pair(m, e);
++ m_table[e->file_descriptor()] = Table::value_type(m, e);
+ }
+
+ inline void
+@@ -70,7 +70,7 @@
+
+ epoll_event e;
+ e.data.u64 = 0; // Make valgrind happy? Remove please.
+- e.data.ptr = event;
++ e.data.fd = event->file_descriptor();
+ e.events = mask;
+
+ set_event_mask(event, mask);
+@@ -138,20 +138,25 @@
+ void
+ PollEPoll::perform() {
+ for (epoll_event *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr) {
++ if (itr->data.fd < 0 || (size_t)itr->data.fd >= m_table.size())
++ continue;
++
++ Table::iterator evItr = m_table.begin() + itr->data.fd;
++
+ // Each branch must check for data.ptr != NULL to allow the socket
+ // to remove itself between the calls.
+ //
+ // TODO: Make it so that it checks that read/write is wanted, that
+ // it wasn't removed from one of them but not closed.
+
+- if (itr->events & EPOLLERR && itr->data.ptr != NULL && event_mask((Event*)itr->data.ptr) & EPOLLERR)
+- ((Event*)itr->data.ptr)->event_error();
++ if (itr->events & EPOLLERR && evItr->second != NULL && evItr->first & EPOLLERR)
++ evItr->second->event_error();
+
+- if (itr->events & EPOLLIN && itr->data.ptr != NULL && event_mask((Event*)itr->data.ptr) & EPOLLIN)
+- ((Event*)itr->data.ptr)->event_read();
++ if (itr->events & EPOLLIN && evItr->second != NULL && evItr->first & EPOLLIN)
++ evItr->second->event_read();
+
+- if (itr->events & EPOLLOUT && itr->data.ptr != NULL && event_mask((Event*)itr->data.ptr) & EPOLLOUT)
+- ((Event*)itr->data.ptr)->event_write();
++ if (itr->events & EPOLLOUT && evItr->second != NULL && evItr->first & EPOLLOUT)
++ evItr->second->event_write();
+ }
+
+ m_waitingEvents = 0;
+@@ -173,9 +178,14 @@
+ if (event_mask(event) != 0)
+ throw internal_error("PollEPoll::close(...) called but the file descriptor is active");
+
++ m_table[event->file_descriptor()] = Table::value_type();
++
++ /*
++ Shouldn't be needed anymore.
+ for (epoll_event *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr)
+ if (itr->data.ptr == event)
+ itr->data.ptr = NULL;
++ */
+ }
+
+ void
+@@ -183,12 +193,14 @@
+ // Kernel removes closed FDs automatically, so just clear the mask and remove it from pending calls.
+ // Don't touch if the FD was re-used before we received the close notification.
+ if (m_table[event->file_descriptor()].second == event)
+- set_event_mask(event, 0);
++ m_table[event->file_descriptor()] = Table::value_type();
+
++ /*
+ for (epoll_event *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr) {
+ if (itr->data.ptr == event)
+ itr->data.ptr = NULL;
+ }
++ */
+ }
+
+ // Use custom defines for EPOLL* to make the below code compile with
+Index: libtorrent/src/torrent/poll_kqueue.cc
+===================================================================
+--- libtorrent/src/torrent/poll_kqueue.cc (revision 1072)
++++ libtorrent/src/torrent/poll_kqueue.cc (working copy)
+@@ -70,7 +70,7 @@
+ PollKQueue::set_event_mask(Event* e, uint32_t m) {
+ assert(e->file_descriptor() != -1);
+
+- m_table[e->file_descriptor()] = std::make_pair(m, e);
++ m_table[e->file_descriptor()] = Table::value_type(m, e);
+ }
+
+ void
+@@ -87,7 +87,7 @@
+
+ void
+ PollKQueue::modify(Event* event, unsigned short op, short mask) {
+- // Flush the changed filters to the kernel if the buffer if full.
++ // Flush the changed filters to the kernel if the buffer is full.
+ if (m_changedEvents == m_table.size())
+ flush_events();
+
+@@ -100,7 +100,8 @@
+
+ struct kevent* itr = m_changes + (m_changedEvents++);
+
+- EV_SET(itr, event->file_descriptor(), mask, op, 0, 0, event);
++ assert(event == m_table[event->file_descriptor()].second);
++ EV_SET(itr, event->file_descriptor(), mask, op, 0, 0, NULL);
+ }
+
+ PollKQueue*
+@@ -196,8 +197,9 @@
+ return nfds;
+
+ if (FD_ISSET(0, readSet)) {
++ m_events[m_waitingEvents].ident = 0;
+ m_events[m_waitingEvents].filter = EVFILT_READ;
+- m_events[m_waitingEvents].udata = m_stdinEvent;
++ m_events[m_waitingEvents].flags = 0;
+ m_waitingEvents++;
+ }
+
+@@ -208,19 +210,24 @@
+ void
+ PollKQueue::perform() {
+ for (struct kevent *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr) {
+- if ((itr->flags & EV_ERROR) && itr->udata != NULL) {
+- if (event_mask((Event*)itr->udata) & flag_error)
+- ((Event*)itr->udata)->event_error();
++ if (itr->ident < 0 || itr->ident >= m_table.size())
+ continue;
++
++ Table::iterator evItr = m_table.begin() + itr->ident;
++
++ if ((itr->flags & EV_ERROR) && evItr->second != NULL) {
++ if (evItr->first & flag_error)
++ evItr->second->event_error();
++ continue;
+ }
+
+ // Also check current mask.
+
+- if (itr->filter == EVFILT_READ && itr->udata != NULL && event_mask((Event*)itr->udata) & flag_read)
+- ((Event*)itr->udata)->event_read();
++ if (itr->filter == EVFILT_READ && evItr->second != NULL && evItr->first & flag_read)
++ evItr->second->event_read();
+
+- if (itr->filter == EVFILT_WRITE && itr->udata != NULL && event_mask((Event*)itr->udata) & flag_write)
+- ((Event*)itr->udata)->event_write();
++ if (itr->filter == EVFILT_WRITE && evItr->second != NULL && evItr->first & flag_write)
++ evItr->second->event_write();
+ }
+
+ m_waitingEvents = 0;
+@@ -249,11 +256,16 @@
+ if (event_mask(event) != 0)
+ throw internal_error("PollKQueue::close(...) called but the file descriptor is active");
+
++ m_table[event->file_descriptor()] = Table::value_type();
++
++ /*
++ Shouldn't be needed anymore.
+ for (struct kevent *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr)
+ if (itr->udata == event)
+ itr->udata = NULL;
+
+ m_changedEvents = std::remove_if(m_changes, m_changes + m_changedEvents, rak::equal(event, rak::mem_ref(&kevent::udata))) - m_changes;
++ */
+ }
+
+ void
+@@ -269,14 +281,16 @@
+ // and remove it from pending calls. Don't touch if the FD was
+ // re-used before we received the close notification.
+ if (m_table[event->file_descriptor()].second == event)
+- set_event_mask(event, 0);
++ m_table[event->file_descriptor()] = Table::value_type();
+
++ /*
+ for (struct kevent *itr = m_events, *last = m_events + m_waitingEvents; itr != last; ++itr) {
+ if (itr->udata == event)
+ itr->udata = NULL;
+ }
+
+ m_changedEvents = std::remove_if(m_changes, m_changes + m_changedEvents, rak::equal(event, rak::mem_ref(&kevent::udata))) - m_changes;
++ */
+ }
+
+ // Use custom defines for EPOLL* to make the below code compile with
================================================================
More information about the pld-cvs-commit
mailing list