Add stacktrace for fiber cpp lib.

This commit is contained in:
zhengshuxin 2023-01-11 10:22:33 +08:00
parent 0864514ae4
commit 758dd3852a
11 changed files with 347 additions and 9 deletions

View File

@ -7,8 +7,8 @@ ARFL = rv
#ARFL = cru
RANLIB = ${ENV_RANLIB}
#JMP_CTX = USE_CONTEXT
JMP_CTX = USE_JMP_DEF
JMP_CTX = USE_CONTEXT
#JMP_CTX = USE_JMP_DEF
#JMP_CTX = USE_BOOST_JMP
CFLAGS = -c -g -W \
@ -25,7 +25,7 @@ CFLAGS = -c -g -W \
-Wcast-qual \
-DUSE_FAST_RING \
-O3 \
#-DDEBUG_STACK \
-DDEBUG_STACK \
#-DUSE_VALGRIND \
#-DUSE_INLINE_MEMCPY\
#-DUSE_FAST_TIME \

View File

@ -10,7 +10,7 @@ extern "C" {
typedef struct ACL_FIBER_ATTR {
unsigned int oflag;
#define ACL_FIBER_ATTR_SHARE_STACK (unsigned) 1 << 0
#define ACL_FIBER_ATTR_SHARE_STACK (unsigned) (1 << 0)
size_t stack_size;
} ACL_FIBER_ATTR;
@ -64,7 +64,7 @@ typedef struct ACL_FIBER_STACK {
size_t size;
} ACL_FIBER_STACK;
FIBER_API ACL_FIBER_STACK *acl_fiber_stacktrace(ACL_FIBER *fiber, size_t max);
FIBER_API ACL_FIBER_STACK *acl_fiber_stacktrace(const ACL_FIBER *fiber, size_t max);
FIBER_API void acl_fiber_stackfree(ACL_FIBER_STACK *stack);
/**

View File

@ -60,9 +60,9 @@ typedef struct FIBER_UNIX {
#ifdef DEBUG_STACK
#include <libunwind.h>
ACL_FIBER_STACK *acl_fiber_stacktrace(ACL_FIBER *fiber, size_t max)
ACL_FIBER_STACK *acl_fiber_stacktrace(const ACL_FIBER *fiber, size_t max)
{
FIBER_UNIX *fb = (FIBER_UNIX*) fiber;
const FIBER_UNIX *fb = (const FIBER_UNIX*) fiber;
unw_cursor_t cursor;
unw_word_t off, pc;
ACL_FIBER_STACK *stack;

View File

@ -1,5 +1,7 @@
#pragma once
#include <stddef.h>
#include <string>
#include <vector>
#include "fiber_cpp_define.hpp"
struct ACL_FIBER;
@ -15,6 +17,17 @@ typedef enum
FIBER_EVENT_T_IO_URING, // Linux
} fiber_event_t;
class FIBER_CPP_API fiber_frame
{
public:
fiber_frame(void) : pc(0), off(0) {}
~fiber_frame(void) {}
std::string func;
long pc;
long off;
};
/**
*
*/
@ -86,6 +99,7 @@ public:
*/
void set_errno(int errnum);
public:
/**
*
* @return {const char*}
@ -247,6 +261,15 @@ public:
static void fiber_create(void (*fn)(ACL_FIBER*, void*),
void* ctx, size_t size);
/**
*
* @param fb {const fiber&}
* @param out {std::vector<stack_frame>&}
* @param max {size_t}
*/
static void stacktrace(const fiber& fb, std::vector<fiber_frame>& out,
size_t max = 50);
protected:
/**
* start

View File

@ -299,6 +299,25 @@ void fiber::fiber_create(void (*fn)(ACL_FIBER*, void*), void* ctx, size_t size)
acl_fiber_create(fn, (void*) ctx, size);
}
void fiber::stacktrace(const fiber& fb, std::vector<fiber_frame>& out, size_t max)
{
ACL_FIBER *f = fb.get_fiber();
ACL_FIBER_STACK *stack = acl_fiber_stacktrace(f, max);
if (stack == NULL) {
return;
}
for (size_t i = 0; i < stack->count; i++) {
fiber_frame frame;
frame.func = stack->frames[i].func;
frame.pc = stack->frames[i].pc;
frame.off = stack->frames[i].off;
out.push_back(frame);
}
acl_fiber_stackfree(stack);
}
//////////////////////////////////////////////////////////////////////////////
fiber_timer::fiber_timer(void)

View File

@ -1,8 +1,7 @@
CC = g++
CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \
-Waggregate-return -Wno-long-long \
-Wpointer-arith -Werror -Wshadow -O3 \
-Wno-long-long -Wpointer-arith -Werror -Wshadow -O3 \
-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO
###########################################################

View File

@ -0,0 +1,6 @@
# Don't build the sample on MacOS because libunwind don't support it.
include ./Makefile.in
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
SYSLIB += -lunwind -lunwind-x86_64
endif
PROG = fiber_stack

View File

@ -0,0 +1,174 @@
CC = g++
CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \
-Wno-long-long -Wpointer-arith -Werror -Wshadow -O0 \
-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO
###########################################################
#Check system:
# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX
SYSLIB = -ldl -lpthread -lz
CHECKSYSRES = @echo "Unknow system type!";exit 1
UNIXNAME = $(shell uname -sm)
OSTYPE = $(shell uname -p)
RPATH = linux64
ifeq ($(CC),)
CC = g++
endif
OS_ENV=$(shell uname -a)
ifeq ($(findstring WSL, $(OS_ENV)), WSL)
SYSLIB += -liconv
endif
ifeq ($(findstring ubuntu, $(OS_ENV)), ubuntu)
SYSLIB += -liconv
endif
ifeq ($(findstring Alpine, $(shell uname -a)), Alpine)
SYSLIB += -lucontext
endif
ifeq ($(findstring g++, $(CC)), g++)
GCC_VERSION:=$(shell echo `gcc --version|grep ^gcc|cut -d' ' -f3`)
GCC_MAJOR:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f1)
GCC_MINOR:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f2)
GCC_VER:=$(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -ge 7 \) ] && echo true)
ifeq ($(GCC_VER), true)
CFLAGS += -std=c++11 -DACL_USE_CPP11
endif
endif
# For FreeBSD
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
ifeq ($(findstring gcc, $(CC)), gcc)
CFLAGS += -Wstrict-prototypes
endif
CFLAGS += -DFREEBSD -D_REENTRANT
SYSLIB = -lcrypt -lpthread -lz
RPATH = freebsd
endif
# For Darwin
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
# CC += -arch x86_64 -arch arm64
CFLAGS += -DMACOSX -Wno-invalid-source-encoding \
-Wno-invalid-offsetof
UNIXTYPE = MACOSX
SYSLIB += -liconv -rdynamic
RPATH = macos
endif
#Path for Linux
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
ifeq ($CC, "gcc")
CFLAGS += -Wstrict-prototypes
endif
ifeq ($(findstring i686, $(OSTYPE)), i686)
RPATH = linux32
endif
ifeq ($(findstring x86_64, $(OSTYPE)), x86_64)
RPATH = linux64
endif
ifeq ($(HAS_IO_URING), yes)
SYSLIB += -luring
endif
ifeq ($(has_io_uring), yes)
SYSLIB += -luring
endif
# CFLAGS += -DLINUX2 -D_REENTRANT
CFLAGS += -D_REENTRANT
SYSLIB += -lcrypt
endif
#Path for SunOS
ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS)
ifeq ($(findstring 86, $(UNIXNAME)), 86)
SYSLIB += -lsocket -lnsl -lrt
endif
ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u)
SYSLIB += -lsocket -lnsl -lrt
endif
ifeq ($CC, "gcc")
CFLAGS += -Wstrict-prototypes
endif
CFLAGS += -DSUNOS5 -D_REENTRANT
RPATH = sunos_x86
endif
#Path for HP-UX
ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX)
ifeq ($CC, "gcc")
CFLAGS += -Wstrict-prototypes
endif
CFLAGS += -DHP_UX -DHPUX11
PLAT_NAME=hp-ux
endif
# For CYGWIN
ifeq ($(findstring CYGWIN, $(UNIXNAME)), CYGWIN)
SYSLIB = -lpthread -rdynamic
CFLAGS += -DLINUX2 -DMINGW
UNIXTYPE = LINUX
endif
# For MINGW
ifeq ($(findstring MINGW, $(UNIXNAME)), MINGW)
SYSLIB = -lpthread -rdynamic
CFLAGS += -DLINUX2 -DMINGW
UNIXTYPE = LINUX
endif
# For MSYS
ifeq ($(findstring MSYS, $(UNIXNAME)), MSYS)
SYSLIB = -lpthread -rdynamic
CFLAGS += -DLINUX2 -DMINGW
UNIXTYPE = LINUX
endif
#Find system type.
ifneq ($(SYSPATH),)
CHECKSYSRES = @echo "System is $(shell uname -sm)"
endif
###########################################################
CFLAGS += -I.. -I../../../lib_acl/include -I../../../lib_protocol/include -I../../../lib_acl_cpp/include \
-I../../../lib_fiber/c/include -I../../../lib_fiber/cpp/include
EXTLIBS =
LDFLAGS = -L../../../lib_fiber/lib -lfiber_cpp \
-L../../../lib_acl_cpp/lib -lacl_cpp \
-L../../../lib_protocol/lib -lprotocol \
-L../../../lib_acl/lib -lacl \
-lfiber $(EXTLIBS) $(SYSLIB)
COMPILE = $(CC) $(CFLAGS)
LINK = $(CC) $(OBJ) $(LDFLAGS)
###########################################################
OBJ_PATH = .
#Project's objs
SRC = $(wildcard *.cpp)
OBJ = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(notdir $(SRC)))
$(OBJ_PATH)/%.o: %.cpp
$(COMPILE) $< -o $@
.PHONY = all clean
all: RM $(OBJ)
$(LINK) -o $(PROG)
@echo ""
@echo "All ok! Output:$(PROG)"
@echo ""
RM:
rm -f $(PROG)
clean cl:
rm -f $(PROG)
rm -f $(OBJ)
rebuild rb: clean all
install:
cp $(PROG) ../../../dist/master/libexec/$(RPATH)/
cp $(PROG).cf ../../../dist/master/conf/service/
###########################################################

View File

@ -0,0 +1,92 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
class myfiber : public acl::fiber
{
public:
myfiber(acl::fiber_tbox<bool>& box) : box_(box) {}
~myfiber(void) {}
private:
acl::fiber_tbox<bool>& box_;
// @override
void run(void)
{
printf("fiber-%d-%d running\r\n", get_id(), acl::fiber::self());
func1();
delete this;
}
void func1(void)
{
func2();
}
void func2(void)
{
func3();
}
void func3(void)
{
box_.pop();
}
};
class checker : public acl::fiber
{
public:
checker(acl::fiber_tbox<bool>& box, acl::fiber* fb, int n)
: box_(box), fb_(fb), count_(n) {}
~checker(void) {}
private:
acl::fiber_tbox<bool>& box_;
acl::fiber* fb_;
int count_;
void run(void)
{
std::vector<acl::fiber_frame> stack;
for (int i = 0; i < count_; i++) {
acl::fiber::stacktrace(*fb_, stack, 50);
show_stack(stack);
printf("\r\n");
stack.clear();
sleep(2);
}
box_.push(NULL);
delete this;
}
void show_stack(const std::vector<acl::fiber_frame>& stack)
{
for (std::vector<acl::fiber_frame>::const_iterator
cit = stack.begin(); cit != stack.end(); ++cit) {
printf("0x%lx(%s)+0x%lx\r\n",
(*cit).pc, (*cit).func.c_str(), (*cit).off);
}
}
};
int main(void)
{
acl::acl_cpp_init();
acl::log::stdout_open(true);
acl::fiber_tbox<bool> box;
acl::fiber* f = new myfiber(box);
f->start();
acl::fiber* f2 = new checker(box, f, 10);
f2->start();
acl::fiber::schedule();
return 0;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,24 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//
#pragma once
//#include <iostream>
//#include <tchar.h>
// TODO: 在此处引用程序要求的附加头文件
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/fiber.hpp"
#ifdef ACL_USE_CPP11
#include "fiber/go_fiber.hpp"
#endif
#ifdef WIN32
#define snprintf _snprintf
#endif