#include "vendor_base.h" #include "vendor_global.h" #include #include namespace vendor { struct event_base *eventBase_ = nullptr; LongOpts::LongOpts(const MyOpt opts[], const int size) { myOpt = opts; sizeOpt = size; } void LongOpts::GetOptions(option *opts, std::string &shorts) { for (int i = 0; i < sizeOpt; i++) { // printf("val: %d(%c) ", myOpt[i].val, myOpt[i].val); opts[i].name = strdup(myOpt[i].name); opts[i].has_arg = myOpt[i].has_arg; opts[i].flag = NULL; opts[i].val = myOpt[i].val; if (myOpt[i].val == 0) { continue; } if (myOpt[i].has_arg == no_argument) { shorts.push_back(static_cast(myOpt[i].val)); } else if (myOpt[i].has_arg == required_argument) { shorts.push_back(static_cast(myOpt[i].val)); shorts.push_back(':'); } else { shorts.push_back(static_cast(myOpt[i].val)); } } } MyOpt LongOpts::GetOption(char ch, int index) { if (ch == 0) { return myOpt[index]; } for (int i = 0; i < sizeOpt; i++) { if (myOpt[i].val == ch) { return myOpt[i]; } } return myOpt[0]; } VendorBase::VendorBase() { HTELINK_LOG_ENABLE(true); eventBase_ = event_base_new(); if (eventBase_ == nullptr) { HTELINK_LOG_ERR("event new failed, %s", strerror(errno)); } } VendorBase::~VendorBase() { if (eventBase_ == nullptr) { return; } Exit(SIGINT); event_base_free(eventBase_); } int VendorBase::Exec() { HTELINK_LOG_INFO("register event..."); // 注册信号事件 event_add(evsignal_new(eventBase_, SIGSEGV, VendorBase::SignalHandler, this), NULL); event_add(evsignal_new(eventBase_, SIGFPE, VendorBase::SignalHandler, this), NULL); event_add(evsignal_new(eventBase_, SIGINT, VendorBase::SignalHandler, this), NULL); event_add(evsignal_new(eventBase_, SIGTERM, VendorBase::SignalHandler, this), NULL); event_add(evsignal_new(eventBase_, SIGTSTP, VendorBase::SignalHandler, this), NULL); signal(SIGPIPE, SIG_IGN); HTELINK_LOG_INFO("start to Run"); // struct event *timer_ev = event_new( // eventBase_, -1, EV_PERSIST, // [](evutil_socket_t ev, short e, void *arg) { // VendorBase *vendorBase = static_cast(arg); // vendorBase->Run(); // }, // this); // event_add(timer_ev, NULL); std::thread fn([this] { Run(); }); fn.detach(); // 其他业务 HTELINK_LOG_INFO("start to deamon..."); return event_base_dispatch(eventBase_); } void VendorBase::Exit(int signal) { Stop(signal); if (eventBase_ == nullptr) { return; } char dumpFile[VENDOR_MAX_PATH_SIZE]; sprintf(dumpFile, "%s/event_stat_%s.txt", VENDOR_LOG_PATH.c_str(), utils::nowtostr().c_str()); FILE *fp = fopen(dumpFile, "a"); event_base_dump_events(eventBase_, fp); fclose(fp); event_base_loopbreak(eventBase_); } void VendorBase::SignalHandler(int fd, short event, void *arg) { if (event != EV_SIGNAL) { HTELINK_LOG_ERR("fd: %d, event: %d occur", fd, event); return; } void *l_buffer[512]; char **l_ptrace; int signal = fd; VendorBase *vendorBase = static_cast(arg); if (vendorBase) { vendorBase->Exit(signal); } HTELINK_LOG_ERR("\r\n=========>>>catch signal %d <<<=========", signal); HTELINK_LOG_ERR("Dump stack start..."); int size = backtrace(l_buffer, 512); l_ptrace = backtrace_symbols(l_buffer, size); if (NULL == l_ptrace) { HTELINK_LOG_ERR("backtrace_symbols"); exit(1); } for (int i = 0; i < size; i++) { HTELINK_LOG_ERR(" [%02d] %s", i, l_ptrace[i]); } HTELINK_LOG_ERR("Dump stack end..."); free(l_ptrace); exit(signal); } int32_t VendorBase::ParseOptionArgs(VendorBase *vendor, int argc, char *argv[]) { int longindex = 0; std::string shorts; struct option longopts[vendor->GetOptSize()]; LongOpts longOpts(vendor->GetOpts(), vendor->GetOptSize()); longOpts.GetOptions(longopts, shorts); int ch; while ((ch = getopt_long(argc, argv, shorts.c_str(), longopts, &longindex)) != -1) { MyOpt myOpt = longOpts.GetOption(ch, longindex); printf("longindex :%d, opt %d(%c), name:%s , optarg :%s\n", longindex, myOpt.val, myOpt.val, myOpt.name, optarg == nullptr ? "nullptr" : optarg); if (strcmp(myOpt.name, "help") == 0) { MyOpt *myOpts = vendor->GetOpts(); printf("Usage: %s [OPTION] -l URL\n\nOPTIONS:\n", vendor->Name().c_str()); for (int i = 1; i < vendor->GetOptSize(); i++) { if (myOpts[i].val == 0) { printf("--%s: %s\n", myOpts[i].name, myOpts[i].desc); } else { printf("-%c, --%s: %s\n", myOpts[i].val, myOpts[i].name, myOpts[i].desc); } } return -1; } if (vendor->ParseCmdline(myOpt.name, optarg == nullptr ? "" : optarg) != 0) { printf("parse failed!!!\n"); return -1; } } return 0; } }; // namespace vendor