Modified: trunk/Source/WebKit2/ChangeLog (128288 => 128289)
--- trunk/Source/WebKit2/ChangeLog 2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/ChangeLog 2012-09-12 10:20:00 UTC (rev 128289)
@@ -1,3 +1,35 @@
+2012-09-12 Byungwoo Lee <bw80....@samsung.com>
+
+ [EFL][WK2] WorkQueue::dispatchAfterDelay() doesn't work properly.
+ https://bugs.webkit.org/show_bug.cgi?id=91179
+
+ Reviewed by Gyuyoung Kim.
+
+ When UI Process is crashed and WebProcess's ecore main loop is very
+ busy or lockup also, watchdocCallback() function in the
+ ChildProcess.cpp doesn't triggered. And this is because of that
+ WorkQueue::dispatchAfterDelay() function uses ecore timer for getting
+ timer event.
+
+ For removing the dependency between the dispatchAfterDelay() and ecore
+ main loop, new timer event mechanism is added to WorkQueue main loop.
+
+ * Platform/WorkQueue.h:
+ (TimerWorkItem):
+ (WorkQueue::TimerWorkItem::dispatch):
+ (WorkQueue::TimerWorkItem::expireTime):
+ (WorkQueue::TimerWorkItem::expired):
+ (WorkQueue):
+ * Platform/efl/WorkQueueEfl.cpp:
+ (WorkQueue::TimerWorkItem::create):
+ (WorkQueue::TimerWorkItem::TimerWorkItem):
+ (WorkQueue::performFileDescriptorWork):
+ (WorkQueue::getCurrentTime):
+ (WorkQueue::getNextTimeOut):
+ (WorkQueue::performTimerWork):
+ (WorkQueue::workQueueThread):
+ (WorkQueue::dispatchAfterDelay):
+
2012-09-12 Christophe Dumez <christophe.du...@intel.com>
[WK2][WKTR] TestRunner needs to implement dumpApplicationCacheDelegateCallbacks
Modified: trunk/Source/WebKit2/Platform/WorkQueue.h (128288 => 128289)
--- trunk/Source/WebKit2/Platform/WorkQueue.h 2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/Platform/WorkQueue.h 2012-09-12 10:20:00 UTC (rev 128289)
@@ -187,6 +187,21 @@
HashMap<int, Vector<EventSource*> > m_eventSources;
typedef HashMap<int, Vector<EventSource*> >::iterator EventSourceIterator;
#elif PLATFORM(EFL)
+ class TimerWorkItem {
+ public:
+ static PassOwnPtr<TimerWorkItem> create(Function<void()>, double expireTime);
+ void dispatch() { m_function(); }
+ double expireTime() const { return m_expireTime; }
+ bool expired(double currentTime) const { return currentTime >= m_expireTime; }
+
+ protected:
+ TimerWorkItem(Function<void()>, double expireTime);
+
+ private:
+ Function<void()> m_function;
+ double m_expireTime;
+ };
+
fd_set m_fileDescriptorSet;
int m_maxFileDescriptor;
int m_readFromPipeDescriptor;
@@ -199,13 +214,17 @@
int m_socketDescriptor;
Function<void()> m_socketEventHandler;
- HashMap<int, OwnPtr<Ecore_Timer> > m_timers;
+ Vector<OwnPtr<TimerWorkItem> > m_timerWorkItems;
+ Mutex m_timerWorkItemsLock;
void sendMessageToThread(const char*);
static void* workQueueThread(WorkQueue*);
void performWork();
void performFileDescriptorWork();
- static bool timerFired(void*);
+ static double getCurrentTime();
+ struct timeval* getNextTimeOut();
+ void performTimerWork();
+ void insertTimerWorkItem(PassOwnPtr<TimerWorkItem>);
#endif
};
Modified: trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp (128288 => 128289)
--- trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp 2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp 2012-09-12 10:20:00 UTC (rev 128289)
@@ -20,34 +20,29 @@
#include "config.h"
#include "WorkQueue.h"
+#include <sys/timerfd.h>
#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
-class TimerWorkItem {
-public:
- TimerWorkItem(int timerID, const Function<void()>& function, WorkQueue* queue)
- : m_function(function)
- , m_queue(queue)
- , m_timerID(timerID)
- {
- }
- ~TimerWorkItem() { }
-
- Function<void()> function() const { return m_function; }
- WorkQueue* queue() const { return m_queue; }
-
- int timerID() const { return m_timerID; }
-
-private:
- Function<void()> m_function;
- WorkQueue* m_queue;
- int m_timerID;
-};
-
static const int invalidSocketDescriptor = -1;
static const int threadMessageSize = 1;
static const char finishThreadMessage[] = "F";
static const char wakupThreadMessage[] = "W";
+PassOwnPtr<WorkQueue::TimerWorkItem> WorkQueue::TimerWorkItem::create(Function<void()> function, double expireTime)
+{
+ if (expireTime < 0)
+ return nullptr;
+
+ return adoptPtr(new TimerWorkItem(function, expireTime));
+}
+
+WorkQueue::TimerWorkItem::TimerWorkItem(Function<void()> function, double expireTime)
+ : m_function(function)
+ , m_expireTime(expireTime)
+{
+}
+
void WorkQueue::platformInitialize(const char* name)
{
int fds[2];
@@ -91,7 +86,7 @@
{
fd_set readFileDescriptorSet = m_fileDescriptorSet;
- if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, 0) >= 0) {
+ if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, getNextTimeOut()) >= 0) {
if (FD_ISSET(m_readFromPipeDescriptor, &readFileDescriptorSet)) {
char readBuf[threadMessageSize];
if (read(m_readFromPipeDescriptor, readBuf, threadMessageSize) == -1)
@@ -105,6 +100,74 @@
}
}
+struct timeval* WorkQueue::getNextTimeOut()
+{
+ MutexLocker locker(m_timerWorkItemsLock);
+ if (m_timerWorkItems.isEmpty())
+ return 0;
+
+ static struct timeval timeValue;
+ timeValue.tv_sec = 0;
+ timeValue.tv_usec = 0;
+ double timeOut = m_timerWorkItems[0]->expireTime() - currentTime();
+ if (timeOut > 0) {
+ timeValue.tv_sec = static_cast<long>(timeOut);
+ timeValue.tv_usec = static_cast<long>((timeOut - timeValue.tv_sec) * 1000000);
+ }
+
+ return &timeValue;
+}
+
+void WorkQueue::insertTimerWorkItem(PassOwnPtr<TimerWorkItem> item)
+{
+ if (!item)
+ return;
+
+ size_t position = 0;
+
+ // m_timerWorkItems should be ordered by expire time.
+ for (; position < m_timerWorkItems.size(); ++position)
+ if (item->expireTime() < m_timerWorkItems[position]->expireTime())
+ break;
+
+ m_timerWorkItems.insert(position, item);
+}
+
+void WorkQueue::performTimerWork()
+{
+ // Protects m_timerWorkItems.
+ m_timerWorkItemsLock.lock();
+
+ if (m_timerWorkItems.isEmpty()) {
+ m_timerWorkItemsLock.unlock();
+ return;
+ }
+
+ double current = currentTime();
+ Vector<OwnPtr<TimerWorkItem> > timerWorkItems;
+
+ // Copies all the timer work items in m_timerWorkItems to local vector.
+ m_timerWorkItems.swap(timerWorkItems);
+
+ for (size_t i = 0; i < timerWorkItems.size(); ++i) {
+ if (!timerWorkItems[i]->expired(current)) {
+ // If a timer work item does not expired, keep it to the m_timerWorkItems.
+ // m_timerWorkItems should be ordered by expire time.
+ insertTimerWorkItem(timerWorkItems[i].release());
+ continue;
+ }
+
+ // If a timer work item expired, dispatch the function of the work item.
+ // Before dispatching, m_timerWorkItemsLock should unlock for preventing deadlock,
+ // because it can be accessed inside the function of the timer work item dispatched.
+ m_timerWorkItemsLock.unlock();
+ timerWorkItems[i]->dispatch();
+ m_timerWorkItemsLock.lock();
+ }
+
+ m_timerWorkItemsLock.unlock();
+}
+
void WorkQueue::sendMessageToThread(const char* message)
{
if (write(m_writeToPipeDescriptor, message, threadMessageSize) == -1)
@@ -115,6 +178,7 @@
{
while (workQueue->m_threadLoop) {
workQueue->performWork();
+ workQueue->performTimerWork();
workQueue->performFileDescriptorWork();
}
@@ -153,21 +217,16 @@
sendMessageToThread(wakupThreadMessage);
}
-bool WorkQueue::timerFired(void* data)
+void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
{
- TimerWorkItem* item = static_cast<TimerWorkItem*>(data);
- if (item && item->queue()->m_isValid) {
- item->queue()->dispatch(item->function());
- item->queue()->m_timers.take(item->timerID());
- delete item;
- }
+ if (delay < 0)
+ return;
- return ECORE_CALLBACK_CANCEL;
-}
+ MutexLocker locker(m_timerWorkItemsLock);
+ OwnPtr<TimerWorkItem> timerWorkItem = TimerWorkItem::create(function, currentTime() + delay);
+ if (!timerWorkItem)
+ return;
-void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
-{
- static int timerId = 1;
- m_timers.set(timerId, adoptPtr(ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerFired), new TimerWorkItem(timerId, function, this))));
- timerId++;
+ insertTimerWorkItem(timerWorkItem.release());
+ sendMessageToThread(wakupThreadMessage);
}