int run(void) { #ifdef USE_ST st_usleep(1); //force context switch so timers will work #endif g_hash_table_foreach(hash, create_q_threads, NULL); #ifdef USE_ST if (debug > 3) { LOG(LOG_DEBUG, "waiting for all threads to finish"); } while (thread_count) { st_usleep(10000); /* 10 ms */ } #endif if (HAVE_OPT(HANGUPSCRIPT) && online) { int status; status = system(OPT_ARG(HANGUPSCRIPT)); if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { LOG(LOG_WARNING, "%s: error %d", OPT_ARG(HANGUPSCRIPT), WEXITSTATUS(status)); } } else { LOG(LOG_ERR, "%s exited abnormally", OPT_ARG(HANGUPSCRIPT)); } } online = FALSE; uw_setproctitle("sleeping"); return 0; }
int SrsThread::start() { int ret = ERROR_SUCCESS; if(tid) { srs_info("thread already running."); return ret; } if((tid = st_thread_create(thread_fun, this, (_joinable? 1:0), 0)) == NULL){ ret = ERROR_ST_CREATE_CYCLE_THREAD; srs_error("st_thread_create failed. ret=%d", ret); return ret; } // we set to loop to true for thread to run. loop = true; // wait for cid to ready, for parent thread to get the cid. while (_cid < 0 && loop) { st_usleep(10 * 1000); } // now, cycle thread can run. can_run = true; return ret; }
void producer(void * d) { printf("producer =%d\n",(int)d); while(1) { while(count>=MAX_COUNT) { printf("=>wait produce=%d count=%d\n",(int)d,count); st_usleep(1000 * 100); } count++; printf("=>produce=%d count=%d\n",(int)d,count); st_usleep(1000 * 100); } }
int SrsServer::do_cycle() { int ret = ERROR_SUCCESS; // find the max loop int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES); max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES); // the deamon thread, update the time cache while (true) { for (int i = 1; i < max + 1; i++) { st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); // for gperf heap checker, // @see: research/gperftools/heap-checker/heap_checker.cc // if user interrupt the program, exit to check mem leak. // but, if gperf, use reload to ensure main return normally, // because directly exit will cause core-dump. #ifdef SRS_AUTO_GPERF_MC if (signal_gmc_stop) { srs_warn("gmc got singal to stop server."); return ret; } #endif if (signal_reload) { signal_reload = false; srs_info("get signal reload, to reload the config."); if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { srs_error("reload config failed. ret=%d", ret); return ret; } srs_trace("reload config success."); } // update the cache time or rusage. if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) { srs_update_system_time_ms(); } if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) { srs_update_system_rusage(); } if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) { srs_update_proc_stat(); } if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) { srs_update_meminfo(); } if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) { srs_update_platform_info(); } } } return ret; }
void SrsEncoder::encoder_cycle() { int ret = ERROR_SUCCESS; log_context->generate_id(); srs_trace("encoder cycle start"); while (loop) { if ((ret = cycle()) != ERROR_SUCCESS) { srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret); } else { srs_info("encoder cycle success, retry"); } if (!loop) { break; } st_usleep(SRS_ENCODER_SLEEP_MS * 1000); } // kill ffmpeg when finished and it alive std::vector<SrsFFMPEG*>::iterator it; for (it = ffmpegs.begin(); it != ffmpegs.end(); ++it) { SrsFFMPEG* ffmpeg = *it; ffmpeg->stop(); } srs_trace("encoder cycle finished"); }
void SrsThread::dispose() { if (disposed) { return; } // the interrupt will cause the socket to read/write error, // which will terminate the cycle thread. st_thread_interrupt(tid); // when joinable, wait util quit. if (_joinable) { // wait the thread to exit. int ret = st_thread_join(tid, NULL); if (ret) { srs_warn("core: ignore join thread failed."); } } // wait the thread actually terminated. // sometimes the thread join return -1, for example, // when thread use st_recvfrom, the thread join return -1. // so here, we use a variable to ensure the thread stopped. // @remark even the thread not joinable, we must ensure the thread stopped when stop. while (!really_terminated) { st_usleep(10 * 1000); if (really_terminated) { break; } srs_warn("core: wait thread to actually terminated"); } disposed = true; }
void consumer(void * d) { printf("consumer =%d\n",(int)d); while(1) { while(0 >= count) { printf("<=========wait consumer=%d count=%d\n",(int)d,count); st_usleep(1000 * 100); } count--; printf("<=========consumer=%d count=%d\n",(int)d,count); st_usleep(1000 * 100); } }
void SrsThread::thread_cycle() { int ret = ERROR_SUCCESS; _srs_context->generate_id(); srs_info("thread cycle start"); _cid = _srs_context->get_id(); srs_assert(handler); handler->on_thread_start(); // wait for cid to ready, for parent thread to get the cid. while (!can_run && loop) { st_usleep(10 * 1000); } while (loop) { if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread on before cycle success"); if ((ret = handler->cycle()) != ERROR_SUCCESS) { srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread cycle success"); if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread on end cycle success"); failed: if (!loop) { break; } st_usleep(cycle_interval_us); } handler->on_thread_stop(); srs_info("thread cycle finished"); }
void run_actual_probes(void) { thread_count = 0; st_usleep(1); //force context switch so timers will work g_hash_table_foreach(cache, add_probe, NULL); while (thread_count) { st_sleep(1); } }
void *_queue_worker(void *arg) { struct rpc_queue *queue; queue = (struct rpc_queue*)arg; arg = NULL; struct rpc_package_head *head; for (; ; st_usleep(10)) { if (worker_thread_count < 1000 && queue->count > 0) { head = queue_get(queue); assert(head != NULL); st_thread_create(_peer_task_worker, head, 0, 0); worker_thread_count ++; } } }
static void *read_queue(void *data) { struct q_info *q = (struct q_info *)data; extern int forever; static char path[PATH_MAX]; G_CONST_RETURN gchar *filename; GDir *dir; q->fatal = 0; //sprintf(path, "%s/%s/new", OPT_ARG(SPOOLDIR), q->name); strcpy(path, OPT_ARG(SPOOLDIR)); strcat(path, "/"); strcat(path, q->name); strcat(path, "/new"); if (debug > 3) { LOG(LOG_DEBUG, "reading queue %s", path); } dir = g_dir_open (path, 0, NULL); while ((filename = g_dir_read_name(dir)) != NULL && !q->fatal && forever) { char buffer[PATH_MAX]; struct thr_data *td; sprintf(buffer, "%s/%s", path, filename); td = g_malloc0(sizeof(struct thr_data)); td->q = q; td->filename = strdup(buffer); #ifdef USE_ST if (st_thread_create(push, td, 0, 0) == NULL) { LOG(LOG_WARNING, "couldn't create thread"); st_sleep(1); } else { q->thread_count++; thread_count++; } while (q->thread_count >= q->maxthreads) { st_usleep(10000); /* 10 ms */ } #else push(td); #endif } g_dir_close(dir); #ifdef USE_ST thread_count--; #endif return NULL; }
int SrsEdgeIngester::ingest() { int ret = ERROR_SUCCESS; client->set_recv_timeout(SRS_EDGE_INGESTER_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_CONSTS_STAGE_EDGE); while (pthread->can_loop()) { // switch to other st-threads. st_usleep(0); pithy_print.elapse(); // pithy print if (pithy_print.can_print()) { kbps->sample(); srs_trace("<- "SRS_CONSTS_LOG_EDGE_PLAY " time=%"PRId64", okbps=%d,%d,%d, ikbps=%d,%d,%d", pithy_print.age(), kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(), kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m()); } // read from client. SrsMessage* msg = NULL; if ((ret = client->recv_message(&msg)) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret)) { srs_error("pull origin server message failed. ret=%d", ret); } return ret; } srs_verbose("edge loop recv message. ret=%d", ret); srs_assert(msg); SrsAutoFree(SrsMessage, msg); if ((ret = process_publish_message(msg)) != ERROR_SUCCESS) { return ret; } } return ret; }
int SrsServer::cycle() { int ret = ERROR_SUCCESS; ret = do_cycle(); #ifdef SRS_AUTO_GPERF_MC destroy(); srs_warn("sleep a long time for system st-threads to cleanup."); st_usleep(3 * 1000 * 1000); srs_warn("system quit"); #else srs_warn("main cycle terminated, system quit normally."); exit(0); #endif return ret; }
void SrsThread::thread_cycle() { int ret = ERROR_SUCCESS; srs_assert(handler); log_context->generate_id(); srs_trace("thread cycle start"); handler->on_end_cycle(); loop = true; while (loop) { if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { srs_warn("thread on before cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread on before cycle success"); if ((ret = handler->cycle()) != ERROR_SUCCESS) { srs_warn("thread cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread cycle success"); if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { srs_warn("thread on end cycle failed, ignored and retry, ret=%d", ret); goto failed; } srs_info("thread on end cycle success"); failed: if (!loop) { break; } st_usleep(cycle_interval_us); } handler->on_leave_loop(); srs_trace("thread cycle finished"); }
// function called by the increment thread // increments the counter, prints the current value, and then // sleeps for some time. void *increment_thread_func(void *s) { ThreadInit *init = s; // cast the void pointer to keep compiler happy int num_inc; for (num_inc = 0; num_inc < DEFAULT_NUM_ITERS; num_inc++) { // decrement the semaphore down(init->bin_sem); // dereference the value pointer, then increment it (*(init->value_ptr))++; // print the current value fprintf(init->output_stream, "%d\n", (*(init->value_ptr))); fflush(init->output_stream); // increment the semaphore up(init->bin_sem); // wait some time st_usleep(INC_SLEEP_TIME); } // all done - thread exits st_thread_exit(NULL); }
int SrsServer::cycle() { int ret = ERROR_SUCCESS; // the deamon thread, update the time cache while (true) { st_usleep(SRS_TIME_RESOLUTION_MS * 1000); srs_update_system_time_ms(); // for gperf heap checker, // @see: research/gperftools/heap-checker/heap_checker.cc // if user interrupt the program, exit to check mem leak. // but, if gperf, use reload to ensure main return normally, // because directly exit will cause core-dump. #ifdef SRS_GPERF_MC if (signal_gmc_stop) { break; } #endif if (signal_reload) { signal_reload = false; srs_info("get signal reload, to reload the config."); if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { srs_error("reload config failed. ret=%d", ret); return ret; } srs_trace("reload config success."); } } #ifdef SRS_INGEST ingester->stop(); #endif return ret; }
/** * More precise sleep() * * Portable usleep() function. * \param delay the amount of time to sleep */ void msleep( mtime_t delay ) { #if defined( HAVE_KERNEL_OS_H ) snooze( delay ); #elif defined( PTH_INIT_IN_PTH_H ) pth_usleep( delay ); #elif defined( ST_INIT_IN_ST_H ) st_usleep( delay ); #elif defined( WIN32 ) || defined( UNDER_CE ) Sleep( (int) (delay / 1000) ); #elif defined( HAVE_NANOSLEEP ) struct timespec ts_delay; ts_delay.tv_sec = delay / 1000000; ts_delay.tv_nsec = (delay % 1000000) * 1000; nanosleep( &ts_delay, NULL ); #else struct timeval tv_delay; tv_delay.tv_sec = delay / 1000000; tv_delay.tv_usec = delay % 1000000; /* select() return value should be tested, since several possible errors * can occur. However, they should only happen in very particular occasions * (i.e. when a signal is sent to the thread, or when memory is full), and * can be ignored. */ select( 0, NULL, NULL, NULL, &tv_delay ); #endif }
int SrsServer::do_cycle() { int ret = ERROR_SUCCESS; // find the max loop int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES); max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_DISK_STAT_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES); max = srs_max(max, SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES); // the deamon thread, update the time cache while (true) { // the interval in config. int heartbeat_max_resolution = (int)(_srs_config->get_heartbeat_interval() / 100); // dynamic fetch the max. int __max = max; __max = srs_max(__max, heartbeat_max_resolution); for (int i = 0; i < __max; i++) { st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); // for gperf heap checker, // @see: research/gperftools/heap-checker/heap_checker.cc // if user interrupt the program, exit to check mem leak. // but, if gperf, use reload to ensure main return normally, // because directly exit will cause core-dump. #ifdef SRS_AUTO_GPERF_MC if (signal_gmc_stop) { srs_warn("gmc got singal to stop server."); return ret; } #endif if (signal_reload) { signal_reload = false; srs_info("get signal reload, to reload the config."); if ((ret = _srs_config->reload()) != ERROR_SUCCESS) { srs_error("reload config failed. ret=%d", ret); return ret; } srs_trace("reload config success."); } // update the cache time or rusage. if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) { srs_info("update current time cache."); srs_update_system_time_ms(); } if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) { srs_info("update resource info, rss."); srs_update_system_rusage(); } if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) { srs_info("update cpu info, cpu usage."); srs_update_proc_stat(); } if ((i % SRS_SYS_DISK_STAT_RESOLUTION_TIMES) == 0) { srs_info("update disk info, disk iops."); srs_update_disk_stat(); } if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) { srs_info("update memory info, usage/free."); srs_update_meminfo(); } if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) { srs_info("update platform info, uptime/load."); srs_update_platform_info(); } if ((i % SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES) == 0) { srs_info("update network devices info."); srs_update_network_devices(); } if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) { srs_info("update network rtmp server info."); resample_kbps(NULL); srs_update_rtmp_server((int)conns.size(), kbps); } #ifdef SRS_AUTO_HTTP_PARSER if (_srs_config->get_heartbeat_enabled()) { if ((i % heartbeat_max_resolution) == 0) { srs_info("do http heartbeat, for internal server to report."); http_heartbeat->heartbeat(); } } #endif srs_info("server main thread loop"); } } return ret; }
int SrsForwarder::forward() { int ret = ERROR_SUCCESS; client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); SrsSharedPtrMessageArray msgs(SYS_MAX_FORWARD_SEND_MSGS); while (pthread->can_loop()) { // switch to other st-threads. st_usleep(0); pithy_print.elapse(); // read from client. if (true) { SrsMessage* msg = NULL; ret = client->recv_message(&msg); srs_verbose("play loop recv message. ret=%d", ret); if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { srs_error("recv server control message failed. ret=%d", ret); return ret; } srs_freep(msg); } // forward all messages. int count = 0; if ((ret = queue->dump_packets(msgs.size, msgs.msgs, count)) != ERROR_SUCCESS) { srs_error("get message to forward failed. ret=%d", ret); return ret; } // pithy print if (pithy_print.can_print()) { kbps->sample(); srs_trace("-> "SRS_LOG_ID_FOWARDER " time=%"PRId64", msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d", pithy_print.age(), count, kbps->get_send_kbps(), kbps->get_send_kbps_30s(), kbps->get_send_kbps_5m(), kbps->get_recv_kbps(), kbps->get_recv_kbps_30s(), kbps->get_recv_kbps_5m()); } // ignore when no messages. if (count <= 0) { srs_verbose("no packets to forward."); continue; } // all msgs to forward. // @remark, becareful, all msgs must be free explicitly, // free by send_and_free_message or srs_freep. for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs.msgs[i]; srs_assert(msg); msgs.msgs[i] = NULL; if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) { srs_error("forwarder send message to server failed. ret=%d", ret); return ret; } } } return ret; }
void SrsThread::thread_cycle() { int ret = ERROR_SUCCESS; _srs_context->generate_id(); srs_info("thread %s cycle start", _name); _cid = _srs_context->get_id(); srs_assert(handler); handler->on_thread_start(); // thread is running now. really_terminated = false; // wait for cid to ready, for parent thread to get the cid. while (!can_run && loop) { st_usleep(10 * 1000); } while (loop) { if ((ret = handler->on_before_cycle()) != ERROR_SUCCESS) { srs_warn("thread %s on before cycle failed, ignored and retry, ret=%d", _name, ret); goto failed; } srs_info("thread %s on before cycle success"); if ((ret = handler->cycle()) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret) && !srs_is_system_control_error(ret)) { srs_warn("thread %s cycle failed, ignored and retry, ret=%d", _name, ret); } goto failed; } srs_info("thread %s cycle success", _name); if ((ret = handler->on_end_cycle()) != ERROR_SUCCESS) { srs_warn("thread %s on end cycle failed, ignored and retry, ret=%d", _name, ret); goto failed; } srs_info("thread %s on end cycle success", _name); failed: if (!loop) { break; } // to improve performance, donot sleep when interval is zero. // @see: https://github.com/ossrs/srs/issues/237 if (cycle_interval_us != 0) { st_usleep(cycle_interval_us); } } // readly terminated now. really_terminated = true; // when thread terminated normally, also disposed. // we must set to disposed before the on_thread_stop, which may free the thread. // @see https://github.com/ossrs/srs/issues/546 disposed = true; handler->on_thread_stop(); srs_info("thread %s cycle finished", _name); }
int st_sleep(int secs) { return st_usleep((secs >= 0) ? secs * (st_utime_t) 1000000LL : ST_UTIME_NO_TIMEOUT); }
int SrsForwarder::forward() { int ret = ERROR_SUCCESS; client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER); while (pthread->can_loop()) { // switch to other st-threads. st_usleep(0); // read from client. if (true) { SrsCommonMessage* msg = NULL; ret = client->recv_message(&msg); srs_verbose("play loop recv message. ret=%d", ret); if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { srs_error("recv server control message failed. ret=%d", ret); return ret; } } // forward all messages. int count = 0; SrsSharedPtrMessage** msgs = NULL; if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { srs_error("get message to forward failed. ret=%d", ret); return ret; } // ignore when no messages. if (count <= 0) { srs_verbose("no packets to forward."); continue; } SrsAutoFree(SrsSharedPtrMessage*, msgs, true); // pithy print pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000); if (pithy_print.can_print()) { srs_trace("-> time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d", pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps()); } // all msgs to forward. for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; srs_assert(msg); msgs[i] = NULL; if ((ret = client->send_message(msg)) != ERROR_SUCCESS) { srs_error("forwarder send message to server failed. ret=%d", ret); return ret; } } } return ret; }
int SrsEdgeForwarder::cycle() { int ret = ERROR_SUCCESS; client->set_recv_timeout(SRS_PULSE_TIMEOUT_US); SrsPithyPrint pithy_print(SRS_STAGE_EDGE); while (pthread->can_loop()) { // switch to other st-threads. st_usleep(0); if (send_error_code != ERROR_SUCCESS) { st_usleep(SRS_EDGE_FORWARDER_ERROR_US); continue; } // read from client. if (true) { SrsMessage* msg = NULL; ret = client->recv_message(&msg); srs_verbose("edge loop recv message. ret=%d", ret); if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) { srs_error("edge forwarder recv server control message failed. ret=%d", ret); send_error_code = ret; continue; } srs_freep(msg); } // forward all messages. int count = 0; SrsSharedPtrMessage** msgs = NULL; if ((ret = queue->get_packets(0, msgs, count)) != ERROR_SUCCESS) { srs_error("get message to forward to origin failed. ret=%d", ret); return ret; } pithy_print.elapse(); // pithy print if (pithy_print.can_print()) { kbps->sample(); srs_trace("-> "SRS_LOG_ID_EDGE_PUBLISH " time=%"PRId64", msgs=%d, okbps=%d,%d,%d, ikbps=%d,%d,%d", pithy_print.age(), count, kbps->get_send_kbps(), kbps->get_send_kbps_sample_high(), kbps->get_send_kbps_sample_medium(), kbps->get_recv_kbps(), kbps->get_recv_kbps_sample_high(), kbps->get_recv_kbps_sample_medium()); } // ignore when no messages. if (count <= 0) { srs_verbose("no packets to forward."); continue; } SrsAutoFreeArray(SrsSharedPtrMessage, msgs, count); // all msgs to forward to origin. // @remark, becareful, all msgs must be free explicitly, // free by send_and_free_message or srs_freep. for (int i = 0; i < count; i++) { SrsSharedPtrMessage* msg = msgs[i]; srs_assert(msg); msgs[i] = NULL; if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) { srs_error("edge publish forwarder send message to server failed. ret=%d", ret); return ret; } } } return ret; }
/** * Wait for a date * * This function uses select() and an system date function to wake up at a * precise date. It should be used for process synchronization. If current date * is posterior to wished date, the function returns immediately. * \param date The date to wake up at */ void mwait( mtime_t date ) { #if defined( HAVE_KERNEL_OS_H ) mtime_t delay; delay = date - real_time_clock_usecs(); if( delay <= 0 ) { return; } snooze( delay ); #elif defined( WIN32 ) || defined( UNDER_CE ) mtime_t usec_time, delay; usec_time = mdate(); delay = date - usec_time; if( delay <= 0 ) { return; } msleep( delay ); #else struct timeval tv_date; mtime_t delay; /* delay in msec, signed to detect errors */ /* see mdate() about gettimeofday() possible errors */ gettimeofday( &tv_date, NULL ); /* calculate delay and check if current date is before wished date */ delay = date - (mtime_t) tv_date.tv_sec * 1000000 - (mtime_t) tv_date.tv_usec - 10000; /* Linux/i386 has a granularity of 10 ms. It's better to be in advance * than to be late. */ if( delay <= 0 ) /* wished date is now or already passed */ { return; } # if defined( PTH_INIT_IN_PTH_H ) pth_usleep( delay ); # elif defined( ST_INIT_IN_ST_H ) st_usleep( delay ); # else # if defined( HAVE_NANOSLEEP ) { struct timespec ts_delay; ts_delay.tv_sec = delay / 1000000; ts_delay.tv_nsec = (delay % 1000000) * 1000; nanosleep( &ts_delay, NULL ); } # else tv_date.tv_sec = delay / 1000000; tv_date.tv_usec = delay % 1000000; /* see msleep() about select() errors */ select( 0, NULL, NULL, NULL, &tv_date ); # endif # endif #endif }