操作方法:
打开wechat.exe,甚至不需要登陆
只需要将鼠标放置于右下角,右键点击调整时间

手动将时间2038年以后

368554_VF7WRPCTV6TWMYC.png

即可触发pc端wechat.exe进程超高cpu占比
如下通过任务管理器可查看到其cpu占比
368554_4DKRQK3UMETVSE3.png

我们对其原因进行分析:
研究了下,对GetSystemTimeAsFileTime进行下断,发现在获取时间的时候、
对于溢出的情况下,将结构体中的第一个变量赋值为0了

368554_MRD493E89TT8N57.png

导致boost得到的时间有关逻辑错误

368554_X6DY53JAJJTC4WT.png

线程的wait失效

进一步通过mars库进行分析分析:
发现在实现条件变量condition的相关代码中
其wait的实现逻辑采用了boost::get_system_time()等函数去获取时间
在create_time[marsboostdate_time microsec_time_clock.hpp]去获取有关本机时间的时候

static time_type create_time(time_converter converter)
    {
#ifdef BOOST_HAS_GETTIMEOFDAY
      timeval tv;
      gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
      std::time_t t = tv.tv_sec;
      boost::uint32_t sub_sec = tv.tv_usec;
#elif defined(BOOST_HAS_FTIME)
      winapi::file_time ft;
      winapi::get_system_time_as_file_time(ft);
      uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
                                                               // and cannot be before 1970-Jan-01
      std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
      // microseconds -- static casts suppress warnings
      mars_boost::uint32_t sub_sec = static_cast<mars_boost::uint32_t>(micros % 1000000UL);
#else
#error Internal Boost.DateTime error: BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK is defined, however neither gettimeofday nor FILETIME support is detected.
#endif
 
      std::tm curr;
      std::tm* curr_ptr = converter(&t, &curr);
      date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
                  static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
                  static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
 
      //The following line will adjust the fractional second tick in terms
      //of the current time system.  For example, if the time system
      //doesn't support fractional seconds then res_adjust returns 0
      //and all the fractional seconds return 0.
      int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000);
 
      time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
                            static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
                            static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
                            sub_sec * adjust);
 
      return time_type(d,td);
    }

走到了BOOST_HAS_GETTIMEOFDAY的代码逻辑里面
原因是未注意其boost库在windows端的有关配置

以及日志库appender.cc为了跨平台操作,采用了结构体timeval + gettimeofday自实现[marscommwindowssystime.c]的方法使其编译可正常通过

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag;
 
  if (NULL != tv)
  {
    GetSystemTimeAsFileTime(&ft);
 
    tmpres |= ft.dwHighDateTime;
    tmpres <<= 32;
    tmpres |= ft.dwLowDateTime;
 
    /*converting file time to unix epoch*/
    tmpres /= 10;  /*convert into microseconds*/
    tmpres -= DELTA_EPOCH_IN_MICROSECS;
 
    tv->tv_sec = ((long)(tmpres / 1000000UL)<0 ? 0 : (long)(tmpres / 1000000UL)); // 注意这里
    tv->tv_usec = (long)(tmpres % 1000000UL);
  }
 
  if (NULL != tz)
  {
    if (!tzflag)
    {
      tzset();
      tzflag++;
    }
    tz->tz_minuteswest = _timezone / 60;
    tz->tz_dsttime = _daylight;
  }
 
  return 0;
}

但如果我们将windows 本机时间变成2038年以后
由于微软所提供的头文件struct timeval里面的tv_sec为4字节,使得tv->tvsec=0
从而导致线程中cond.wait相关功能失效,相当于没有sleep,从而导致cpu高
以及日志库不正常

需要修改

#ifndef WIN32
#define BOOST_HAS_GETTIMEOFDAY
#endif
[mars\boost\config\user.php]

并更新boost库(过于老,而且也存在2038相关逻辑错误)以及建议日志库不使用 timeval 因为这种情况下会导致日志名始终为MM_19700101.xlog以及日志库里时间不正常