移植wvdial后在ARM开发板上运行时出现下列错误:
wvdial: utils/wvtask.cc:198: WvTaskMan::WvTaskMan(): Assertion
`getcontext(&get_stack_return) == 0' failed
Aborted
解决办法:修改代码
--- include/wvtask.h.orig Mon Jul 14 13:11:35 2008 |
+++ include/wvtask.h Mon Nov 23 13:10:28 2009 |
@@ -50,12 +50,10 @@ |
int tid; |
size_t stacksize; |
- void *stack; |
bool running, recycled; |
WvTaskMan &man; |
- ucontext_t mystate; // used for resuming the task |
- ucontext_t func_call, func_return; |
+ jmp_buf mystate; // used for resuming the task |
TaskFunc *func; |
void *userdata; |
@@ -91,16 +89,15 @@ |
static void stackmaster(); |
static void _stackmaster(); |
static void do_task(); |
- static void call_func(WvTask *task); |
static char *stacktop; |
- static ucontext_t stackmaster_task; |
- |
+ static jmp_buf stackmaster_task; |
+ |
static WvTask *stack_target; |
- static ucontext_t get_stack_return; |
- |
+ static jmp_buf get_stack_return; |
+ |
static WvTask *current_task; |
- static ucontext_t toplevel; |
+ static jmp_buf toplevel; |
WvTaskMan(); |
virtual ~WvTaskMan(); |
--- utils/wvtask.cc.orig Wed May 13 15:42:52 2009 |
+++ utils/wvtask.cc Mon Nov 23 13:12:54 2009 |
@@ -32,10 +32,6 @@ |
#include <stdio.h> |
#include <stdlib.h> |
#include <assert.h> |
-#include <sys/mman.h> |
-#include <signal.h> |
-#include <unistd.h> |
-#include <sys/resource.h> |
#ifdef HAVE_VALGRIND_MEMCHECK_H |
#include <valgrind/memcheck.h> |
@@ -60,7 +56,7 @@ |
WvTaskMan *WvTaskMan::singleton; |
int WvTaskMan::links, WvTaskMan::magic_number; |
WvTaskList WvTaskMan::all_tasks, WvTaskMan::free_tasks; |
-ucontext_t WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return, |
+jmp_buf WvTaskMan::stackmaster_task, WvTaskMan::get_stack_return, |
WvTaskMan::toplevel; |
WvTask *WvTaskMan::current_task, *WvTaskMan::stack_target; |
char *WvTaskMan::stacktop; |
@@ -198,9 +194,7 @@ |
stacktop = (char *)alloca(0); |
- context_return = 0; |
- assert(getcontext(&get_stack_return) == 0); |
- if (context_return == 0) |
+ if (setjmp(get_stack_return) == 0) |
{ |
// initial setup - start the stackmaster() task (never returns!) |
stackmaster(); |
@@ -257,22 +251,18 @@ |
WvTask *old_task = current_task; |
current_task = &task; |
- ucontext_t *state; |
+ jmp_buf *state; |
if (!old_task) |
state = &toplevel; // top-level call (not in an actual task yet) |
else |
state = &old_task->mystate; |
- context_return = 0; |
- assert(getcontext(state) == 0); |
- int newval = context_return; |
+ int newval = setjmp(*state); |
if (newval == 0) |
{ |
// saved the state, now run the task. |
- context_return = val; |
- setcontext(&task.mystate); |
- return -1; |
+ longjmp(task.mystate, val); |
} |
else |
{ |
@@ -303,8 +293,6 @@ |
assert(*current_task->stack_magic == WVTASK_MAGIC); |
#if TASK_DEBUG |
- if (use_shared_stack()) |
- { |
size_t stackleft; |
char *stackbottom = (char *)(current_task->stack_magic + 1); |
for (stackleft = 0; stackleft < current_task->stacksize; |
stackleft++) |
@@ -315,18 +303,13 @@ |
Dprintf("WvTaskMan: remaining stack after #%d (%s): %ld/%ld |
/n", |
current_task->tid, current_task->name.cstr(), (long) |
stackleft, |
(long)current_task->stacksize); |
- } |
#endif |
- context_return = 0; |
- assert(getcontext(¤t_task->mystate) == 0); |
- int newval = context_return; |
+ int newval = setjmp(current_task->mystate); |
if (newval == 0) |
{ |
// saved the task state; now yield to the toplevel. |
- context_return = val; |
- setcontext(&toplevel); |
- return -1; |
+ longjmp(toplevel, val); |
} |
else |
{ |
@@ -340,39 +323,14 @@ |
void WvTaskMan::get_stack(WvTask &task, size_t size) |
{ |
- context_return = 0; |
- assert(getcontext(&get_stack_return) == 0); |
- if (context_return == 0) |
+ if (setjmp(get_stack_return) == 0) |
{ |
assert(magic_number == -WVTASK_MAGIC); |
assert(task.magic_number == WVTASK_MAGIC); |
- |
- if (!use_shared_stack()) |
- { |
-#if defined(__linux__) && (defined(__386__) || defined(__i386) || |
defined(__i386__)) |
- static char *next_stack_addr = (char *)0xB0000000; |
- static const size_t stack_shift = 0x00100000; |
- |
- next_stack_addr -= stack_shift; |
-#else |
- static char *next_stack_addr = NULL; |
-#endif |
- |
- task.stack = mmap(next_stack_addr, task.stacksize, |
- PROT_READ | PROT_WRITE, |
-#ifndef MACOS |
- MAP_PRIVATE | MAP_ANONYMOUS, |
-#else |
- MAP_PRIVATE, |
-#endif |
- -1, 0); |
- } |
- |
// initial setup |
stack_target = &task; |
- context_return = size/1024 + (size%1024 > 0); |
- setcontext(&stackmaster_task); |
- } |
+ longjmp(stackmaster_task, size/1024 + (size%1024 > 0)); |
+ } |
else |
{ |
if (current_task) |
@@ -408,9 +366,7 @@ |
{ |
assert(magic_number == -WVTASK_MAGIC); |
- context_return = 0; |
- assert(getcontext(&stackmaster_task) == 0); |
- val = context_return; |
+ val = setjmp(stackmaster_task); |
if (val == 0) |
{ |
assert(magic_number == -WVTASK_MAGIC); |
@@ -418,19 +374,13 @@ |
// just did setjmp; save stackmaster's current state (with |
// all current stack allocations) and go back to get_stack |
// (or the constructor, if that's what called us) |
- context_return = 1; |
- setcontext(&get_stack_return); |
+ longjmp(get_stack_return, 1); |
} |
else |
{ |
valgrind_fix(stacktop); |
assert(magic_number == -WVTASK_MAGIC); |
- total = (val+1) * (size_t)1024; |
- |
- if (!use_shared_stack()) |
- total = 1024; // enough to save the do_task stack |
frame |
- |
// set up a stack frame for the new task. This runs once |
// per get_stack. |
//alloc_stack_and_switch(total); |
@@ -439,6 +389,7 @@ |
assert(magic_number == -WVTASK_MAGIC); |
// allocate the stack area so we never use it again |
+ total = (val+1) * (size_t)1024; |
alloca(total); |
// a little sentinel so we can detect stack overflows |
@@ -455,17 +406,6 @@ |
} |
-void WvTaskMan::call_func(WvTask *task) |
-{ |
- Dprintf("WvTaskMan: calling task #%d (%s)/n", |
- task->tid, (const char *)task->name); |
- task->func(task->userdata); |
- Dprintf("WvTaskMan: returning from task #%d (%s)/n", |
- task->tid, (const char *)task->name); |
- context_return = 1; |
-} |
- |
- |
void WvTaskMan::do_task() |
{ |
assert(magic_number == -WVTASK_MAGIC); |
@@ -473,9 +413,7 @@ |
assert(task->magic_number == WVTASK_MAGIC); |
// back here from longjmp; someone wants stack space. |
- context_return = 0; |
- assert(getcontext(&task->mystate) == 0); |
- if (context_return == 0) |
+ if (setjmp(task->mystate) == 0) |
{ |
// done the setjmp; that means the target task now has |
// a working jmp_buf all set up. Leave space on the stack |
@@ -501,31 +439,11 @@ |
if (task->func && task->running) |
{ |
- if (use_shared_stack()) |
- { |
// this is the task's main function. It can call |
yield() |
// to give up its timeslice if it wants. Either |
way, it |
// only returns to *us* if the function actually |
finishes. |
task->func(task->userdata); |
- } |
- else |
- { |
- assert(getcontext(&task->func_call) == 0); |
- task->func_call.uc_stack.ss_size = task- |
>stacksize; |
- task->func_call.uc_stack.ss_sp = task->stack; |
- task->func_call.uc_stack.ss_flags = 0; |
- task->func_call.uc_link = &task->func_return; |
- Dprintf("WvTaskMan: makecontext #%d (%s)/n", |
- task->tid, (const char *)task->name); |
- makecontext(&task->func_call, |
- (void (*)(void))call_func, 1, task); |
- |
- context_return = 0; |
- assert(getcontext(&task->func_return) == 0); |
- if (context_return == 0) |
- setcontext(&task->func_call); |
- } |
- |
+ |
// the task's function terminated. |
task->name = "DEAD"; |
task->running = false; |
@@ -541,10 +459,7 @@ |
{ |
#ifdef HAVE_LIBC_STACK_END |
extern const void *__libc_stack_end; |
- if (use_shared_stack() || current_task == NULL) |
return __libc_stack_end; |
- else |
- return (const char *)current_task->stack + current_task- |
>stacksize; |
#else |
return 0; |
#endif |
@@ -553,16 +468,7 @@ |
size_t WvTaskMan::current_stacksize_limit() |
{ |
- if (use_shared_stack() || current_task == NULL) |
- { |
- struct rlimit rl; |
- if (getrlimit(RLIMIT_STACK, &rl) == 0) |
- return size_t(rl.rlim_cur); |
- else |
return 0; |
- } |
- else |
- return size_t(current_task->stacksize); |
} |
--- uniconf/unifastregetgen.cc.orig Mon Nov 23 14:31:11 2009 |
+++ uniconf/unifastregetgen.cc Mon Nov 23 14:11:11 2009 |
@@ -54,7 +54,7 @@ |
{ |
if (!tree) |
{ |
- wvassert(tree, "key: '%s'", key); |
+// wvassert(tree, "key: '%s'", key); |
abort(); |
} |
@@ -93,7 +93,7 @@ |
{ |
if (!tree) |
{ |
- wvassert(tree, "key: '%s'", key); |
+// wvassert(tree, "key: '%s'", key); |
abort(); |
} |
--- utils/wvcrash.cc.orig Mon Nov 23 14:32:47 2009 |
+++ utils/wvcrash.cc Mon Nov 23 14:04:08 2009 |
@@ -28,7 +28,7 @@ |
// FIXME: this file mostly only works in Linux |
#ifdef __linux |
-# include <execinfo.h> |
+//#include <execinfo.h> |
#include <unistd.h> |
#ifdef __USE_GNU |
@@ -268,8 +268,8 @@ |
} |
wr(fd, "/nBacktrace:/n"); |
- backtrace_symbols_fd(trace, |
- backtrace(trace, sizeof(trace)/sizeof(trace[0])), fd); |
+// backtrace_symbols_fd(trace, |
+// backtrace(trace, sizeof(trace)/sizeof(trace[0])), fd); |
if (pid > 0) |
{ |
--- uniconf/uniconfkey.cc.orig Mon Nov 23 14:34:08 2009 |
+++ uniconf/uniconfkey.cc Mon Nov 23 13:51:05 2009 |
@@ -324,7 +324,7 @@ |
UniConfKey UniConfKey::subkey(const UniConfKey &key) const |
{ |
UniConfKey answer; |
- wvassert(suborsame(key, answer), |
- "this = '%s'/nkey = '%s'", printable(), key); |
+// wvassert(suborsame(key, answer), |
+// "this = '%s'/nkey = '%s'", printable(), key); |
return answer; |
} |