操作方法: 打开wechat.exe,甚至不需要登陆 只需要将鼠标放置于右下角,右键点击调整时间 手动将时间2038年以后 即可触发pc端wechat.exe进程超高cpu占比 如下通过任务管理器可查看到其cpu占比
我们对其原因进行分析: 研究了下,对GetSystemTimeAsFileTime进行下断,发现在获取时间的时候、 对于溢出的情况下,将结构体中的第一个变量赋值为0了 导致boost得到的时间有关逻辑错误 线程的wait失效
进一步通过mars库进行分析分析: 发现在实现条件变量condition的相关代码中 其wait的实现逻辑采用了boost::get_system_time()等函数去获取时间 在create_time[mars\boost\date_time\ microsec_time_clock.hpp]去获取有关本机时间的时候
走到了BOOST_HAS_GETTIMEOFDAY的代码逻辑里面 原因是未注意其boost库在windows端的有关配置
以及日志库appender.cc为了跨平台操作,采用了结构体timeval + gettimeofday自实现[mars\comm\windows\sys\time.c]的方法使其编译可正常通过
但如果我们将windows 本机时间变成2038年以后 由于微软所提供的头文件struct timeval里面的tv_sec为4字节,使得tv->tvsec=0 从而导致线程中cond .wait相关功能失效,相当于没有sleep,从而导致cpu高 以及日志库不正常
需要修改
并更新boost库(过于老,而且也存在2038相关逻辑错误)以及建议日志库不使用 timeval 因为这种情况下会导致日志名始终为MM_19700101.xlog以及日志库里时间不正常
ps: 还有一些相关bug可参考 https://github.com/Tencent/mars/issues/924 另若mars相关开发人员看见了能否可以考虑开源一下mars的cdn库!!!
static time_type create_time(time_converter converter)
{
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;
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
);
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);
}
static time_type create_time(time_converter converter)
{
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;
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
);
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);
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)