Skip to content

Commit

Permalink
Replace g_time3() with g_get_elapsed_ms()
Browse files Browse the repository at this point in the history
The function as specified used gettimeofday() which is susceptible
to manual time changes, and is obsoleted in POSIX.1-2008. The
replacement uses clock_gettime(CLOCK_MONOTONIC, ) which is not
susceptible to manual time changes (at least on Linux) and cannot run
backwards.

Also, on systems with 32-bit integers, the value returned by this
function wraps around every 49.7 days. To cope with a wraparound in
a way compliant with the C standard, this value needs to return an
unsigned integer type rather than a signed integer type.
  • Loading branch information
matt335672 committed Dec 4, 2024
1 parent 67c7ee1 commit 2742b89
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 56 deletions.
24 changes: 13 additions & 11 deletions common/os_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3764,19 +3764,21 @@ g_check_user_in_group(const char *username, int gid, int *ok)
#endif // HAVE_GETGROUPLIST

/*****************************************************************************/
/* returns time in milliseconds, uses gettimeofday
does not work in win32 */
int
g_time3(void)
unsigned int
g_get_elapsed_ms(void)
{
#if defined(_WIN32)
return 0;
#else
struct timeval tp;
unsigned int result = 0;
struct timespec tp;

gettimeofday(&tp, 0);
return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
#endif
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
{
result = (unsigned int)tp.tv_sec * 1000;
// POSIX 1003.1, 2004 that tv_nsec is a long (i.e. a signed type),
// but can only contain [0..999,999,999]
result += tp.tv_nsec / 1000000;
}

return result;
}

/******************************************************************************/
Expand Down
18 changes: 17 additions & 1 deletion common/os_calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,23 @@ int g_getgroup_info(const char *groupname, int *gid);
* Primary group of username is also checked
*/
int g_check_user_in_group(const char *username, int gid, int *ok);
int g_time3(void);

/**
* Gets elapsed milliseconds since some arbitrary point in the past
*
* The returned value is unaffected by leap-seconds or time zone changes.
*
* @returns elaped ms since some arbirtary point
*
* The value wraps every so often (every 49.7 days on a 32-bit system),
* but as we are using unsigned arithmetic, the difference of any of these
* two values can be used to calculate elapsed time, whether-or-not a wrap
* occurs during the interval - provided of course the time being measured
* is less than the total wraparound interval.
*/
unsigned int
g_get_elapsed_ms(void);

int g_save_to_bmp(const char *filename, char *data, int stride_bytes,
int width, int height, int depth, int bits_per_pixel);
void *g_shmat(int shmid);
Expand Down
12 changes: 6 additions & 6 deletions common/trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,18 +696,18 @@ local_connect_shim(int fd, const char *server, const char *port)
/**************************************************************************//**
* Waits for an asynchronous connect to complete.
* @param self - Transport object
* @param start_time Start time of connect (from g_time3())
* @param start_time Start time of connect (from g_get_elapsed_ms())
* @param timeout Total wait timeout
* @return 0 - connect succeeded, 1 - Connect failed
*
* If the transport is set up for checking a termination object, this
* on a regular basis.
*/
static int
poll_for_async_connect(struct trans *self, int start_time, int timeout)
poll_for_async_connect(struct trans *self, unsigned int start_time, int timeout)
{
int rv = 1;
int ms_remaining = timeout - (g_time3() - start_time);
int ms_remaining = timeout - (g_get_elapsed_ms() - start_time);

while (ms_remaining > 0)
{
Expand Down Expand Up @@ -736,7 +736,7 @@ poll_for_async_connect(struct trans *self, int start_time, int timeout)
break;
}

ms_remaining = timeout - (g_time3() - start_time);
ms_remaining = timeout - (g_get_elapsed_ms() - start_time);
}
return rv;
}
Expand All @@ -747,7 +747,7 @@ int
trans_connect(struct trans *self, const char *server, const char *port,
int timeout)
{
int start_time = g_time3();
unsigned int start_time = g_get_elapsed_ms();
int error;
int ms_before_next_connect;

Expand Down Expand Up @@ -826,7 +826,7 @@ trans_connect(struct trans *self, const char *server, const char *port,
}

/* Have we reached the total timeout yet? */
int ms_left = timeout - (g_time3() - start_time);
int ms_left = timeout - (g_get_elapsed_ms() - start_time);
if (ms_left <= 0)
{
error = 1;
Expand Down
6 changes: 3 additions & 3 deletions sesman/chansrv/chansrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ add_timeout(int msoffset, void (*callback)(void *data), void *data)
tui32 now;

LOG_DEVEL(LOG_LEVEL_DEBUG, "add_timeout:");
now = g_time3();
now = g_get_elapsed_ms();
tobj = g_new0(struct timeout_obj, 1);
tobj->mstime = now + msoffset;
tobj->callback = callback;
Expand Down Expand Up @@ -167,7 +167,7 @@ get_timeout(int *timeout)
tobj = g_timeout_head;
if (tobj != 0)
{
now = g_time3();
now = g_get_elapsed_ms();
while (tobj != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " now %u tobj->mstime %u", now, tobj->mstime);
Expand Down Expand Up @@ -215,7 +215,7 @@ check_timeout(void)
while (tobj != 0)
{
count++;
now = g_time3();
now = g_get_elapsed_ms();
if (now >= tobj->mstime)
{
tobj->callback(tobj->data);
Expand Down
24 changes: 12 additions & 12 deletions sesman/chansrv/sound.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static struct trans *g_audio_c_trans_out = 0; /* connection */
static struct trans *g_audio_l_trans_in = 0; /* listener */
static struct trans *g_audio_c_trans_in = 0; /* connection */

static int g_training_sent_time = 0;
static unsigned int g_training_sent_time = 0;
static int g_cBlockNo = 0;
static int g_bytes_in_stream = 0;
struct fifo *g_in_fifo;
Expand All @@ -86,7 +86,7 @@ static struct stream *g_stream_incoming_packet = NULL;
#define MAX_BBUF_SIZE (1024 * 16)
static char g_buffer[MAX_BBUF_SIZE];
static int g_buf_index = 0;
static int g_sent_time[256];
static unsigned int g_sent_time[256];

static int g_bbuf_size = 1024 * 8; /* may change later */

Expand Down Expand Up @@ -341,15 +341,15 @@ sound_send_training(void)
{
struct stream *s;
int bytes;
int time;
unsigned int time;
char *size_ptr;

make_stream(s);
init_stream(s, 8182);
out_uint16_le(s, SNDC_TRAINING);
size_ptr = s->p;
out_uint16_le(s, 0); /* size, set later */
time = g_time3();
time = g_get_elapsed_ms();
g_training_sent_time = time;
out_uint16_le(s, time);
out_uint16_le(s, 1024);
Expand Down Expand Up @@ -885,7 +885,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
{
struct stream *s;
int bytes;
int time;
unsigned int time;
int format_index;
char *size_ptr;

Expand All @@ -912,7 +912,7 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
out_uint16_le(s, SNDC_WAVE);
size_ptr = s->p;
out_uint16_le(s, 0); /* size, set later */
time = g_time3();
time = g_get_elapsed_ms();
out_uint16_le(s, time);
out_uint16_le(s, format_index); /* wFormatNo */
g_cBlockNo++;
Expand Down Expand Up @@ -1040,7 +1040,7 @@ sound_process_training(struct stream *s, int size)
{
int time_diff;

time_diff = g_time3() - g_training_sent_time;
time_diff = g_get_elapsed_ms() - g_training_sent_time;
LOG(LOG_LEVEL_INFO, "sound_process_training: round trip time %u", time_diff);
return 0;
}
Expand All @@ -1052,12 +1052,12 @@ sound_process_wave_confirm(struct stream *s, int size)
{
int wTimeStamp;
int cConfirmedBlockNo;
int time;
unsigned int time;
int time_diff;
int index;
int acc;

time = g_time3();
time = g_get_elapsed_ms();
in_uint16_le(s, wTimeStamp);
in_uint8(s, cConfirmedBlockNo);
time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff];
Expand Down Expand Up @@ -1095,13 +1095,13 @@ static int
process_pcm_message(int id, int size, struct stream *s)
{
static int sending_silence = 0;
static int silence_start_time = 0;
static unsigned int silence_start_time = 0;
switch (id)
{
case 0:
if ((g_client_does_fdk_aac || g_client_does_mp3lame) && sending_silence)
{
if ((g_time3() - silence_start_time) < (int)g_cfg->msec_do_not_send)
if ((g_get_elapsed_ms() - silence_start_time) < g_cfg->msec_do_not_send)
{
/* do not send data within msec_do_not_send msec after SNDC_CLOSE is sent, to avoid stutter. setting from sesman.ini */
return 0;
Expand All @@ -1119,7 +1119,7 @@ process_pcm_message(int id, int size, struct stream *s)
if (buf != NULL)
{
int i;
silence_start_time = g_time3();
silence_start_time = g_get_elapsed_ms();
sending_silence = 1;
for (i = 0; i < send_silence_times; i++)
{
Expand Down
9 changes: 0 additions & 9 deletions sesman/chansrv/xcommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,6 @@ xcommon_fatal_handler(Display *dis)
return 0;
}

/*****************************************************************************/
/* returns time in milliseconds since a point in the past
this is a time value similar to what the xserver uses */
int
xcommon_get_local_time(void)
{
return g_time3();
}

/******************************************************************************/
/* this should be called first */
int
Expand Down
2 changes: 0 additions & 2 deletions sesman/chansrv/xcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@

typedef void (*x_server_fatal_cb_type)(void);

int
xcommon_get_local_time(void);
int
xcommon_init(void);
int
Expand Down
4 changes: 2 additions & 2 deletions xrdp/xrdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ struct display_control_monitor_layout_data
{
struct display_size_description description;
enum display_resize_state state;
int last_state_update_timestamp;
int start_time;
unsigned int last_state_update_timestamp;
unsigned int start_time;
/// This flag is set if the state machine needs to
/// shutdown/startup EGFX
int using_egfx;
Expand Down
19 changes: 10 additions & 9 deletions xrdp/xrdp_mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1280,9 +1280,9 @@ advance_resize_state_machine(struct xrdp_mm *mm,
description->description.session_height,
XRDP_DISPLAY_RESIZE_STATE_TO_STR(description->state),
XRDP_DISPLAY_RESIZE_STATE_TO_STR(new_state),
g_time3() - description->last_state_update_timestamp);
g_get_elapsed_ms() - description->last_state_update_timestamp);
description->state = new_state;
description->last_state_update_timestamp = g_time3();
description->last_state_update_timestamp = g_get_elapsed_ms();
g_set_wait_obj(mm->resize_ready);
return 0;
}
Expand Down Expand Up @@ -1829,7 +1829,7 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
// ever is, advance the state machine!
if (chan->drdynvcs[mm->egfx->channel_id].status
== XRDP_DRDYNVC_STATUS_CLOSED
|| (g_time3() - description->last_state_update_timestamp) > 100)
|| (g_get_elapsed_ms() - description->last_state_update_timestamp) > 100)
{
advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSED);
break;
Expand Down Expand Up @@ -2045,7 +2045,7 @@ dynamic_monitor_process_queue(struct xrdp_mm *self)
g_malloc(LAYOUT_DATA_SIZE, 1);
g_memcpy(&(self->resize_data->description), queue_head,
sizeof(struct display_size_description));
const int time = g_time3();
const unsigned int time = g_get_elapsed_ms();
self->resize_data->start_time = time;
self->resize_data->last_state_update_timestamp = time;
self->resize_data->using_egfx = (self->egfx != NULL);
Expand Down Expand Up @@ -2075,7 +2075,7 @@ dynamic_monitor_process_queue(struct xrdp_mm *self)
" completed resize (w: %d x h: %d). It took %d milliseconds.",
self->resize_data->description.session_width,
self->resize_data->description.session_height,
g_time3() - self->resize_data->start_time);
g_get_elapsed_ms() - self->resize_data->start_time);
g_set_wait_obj(self->resize_ready);
}
else if (self->resize_data->state == WMRZ_ERROR)
Expand Down Expand Up @@ -3532,9 +3532,10 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self,
{
if (xrdp_region_not_empty(self->wm->screen_dirty_region))
{
int now = g_time3();
int next_screen_draw_time = self->wm->last_screen_draw_time +
MIN_MS_BETWEEN_FRAMES;
unsigned int now = g_get_elapsed_ms();
unsigned int next_screen_draw_time =
self->wm->last_screen_draw_time +
MIN_MS_BETWEEN_FRAMES;
int diff = next_screen_draw_time - now;
int ltimeout = *timeout;
diff = MAX(diff, MIN_MS_TO_WAIT_FOR_MORE_UPDATES);
Expand Down Expand Up @@ -3924,7 +3925,7 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self)
{
if (xrdp_region_not_empty(self->wm->screen_dirty_region))
{
int now = g_time3();
unsigned int now = g_get_elapsed_ms();
int diff = now - self->wm->last_screen_draw_time;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_check_wait_objs: not empty diff %d", diff);
if ((diff < 0) || (diff >= 40))
Expand Down
2 changes: 1 addition & 1 deletion xrdp/xrdp_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ struct xrdp_wm
struct xrdp_tconfig_gfx *gfx_config;

struct xrdp_region *screen_dirty_region;
int last_screen_draw_time;
unsigned int last_screen_draw_time;
};

/* rdp process */
Expand Down

0 comments on commit 2742b89

Please sign in to comment.