dlclose opened libs

This commit is contained in:
Martin Pulec
2019-11-14 08:34:53 +01:00
parent 43a6afd719
commit 71efe75a3f
7 changed files with 100 additions and 65 deletions

View File

@@ -679,8 +679,10 @@ static string format_port_list(struct hd_rum_translator_state *s)
return oss.str();
}
#define EXIT(retval) { common_cleanup(init); return retval; }
int main(int argc, char **argv)
{
struct init_data *init;
struct hd_rum_translator_state state;
int qsize;
@@ -691,8 +693,8 @@ int main(int argc, char **argv)
int i;
struct cmdline_parameters params;
if (!common_preinit(argc, argv)) {
return EXIT_FAILURE;
if ((init = common_preinit(argc, argv)) == nullptr) {
EXIT(EXIT_FAILURE);
}
print_version();
@@ -700,7 +702,7 @@ int main(int argc, char **argv)
if (argc == 1) {
usage(argv[0]);
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
#ifndef WIN32
@@ -722,7 +724,7 @@ int main(int argc, char **argv)
bool ret = parse_fmt(argc, argv, &params);
if (ret == false) {
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
if (params.verbose) {
@@ -731,7 +733,7 @@ int main(int argc, char **argv)
if ((bufsize = atoi(params.bufsize)) <= 0) {
fprintf(stderr, "invalid buffer size: %d\n", bufsize);
return 1;
EXIT(1);
}
switch (params.bufsize[strlen(params.bufsize) - 1]) {
case 'K':
@@ -751,7 +753,7 @@ int main(int argc, char **argv)
if (params.port <= 0) {
fprintf(stderr, "invalid port: %d\n", params.port);
return 1;
EXIT(1);
}
state.qhead = state.qtail = state.queue = qinit(qsize);
@@ -759,7 +761,7 @@ int main(int argc, char **argv)
/* input socket */
if ((sock_in = udp_init_if("localhost", NULL, params.port, 0, 255, false, false)) == NULL) {
perror("input socket");
return 2;
EXIT(2);
}
if (udp_set_recv_buf(sock_in, bufsize) != TRUE) {
@@ -773,7 +775,7 @@ int main(int argc, char **argv)
if (params.control_port != -1) {
if (control_init(params.control_port, params.control_connection_type, &state.control_state, &state.mod, 0) != 0) {
fprintf(stderr, "Warning: Unable to create remote control.\n");
return EXIT_FAIL_CONTROL_SOCK;
EXIT(EXIT_FAIL_CONTROL_SOCK);
}
control_start(state.control_state);
}
@@ -781,7 +783,7 @@ int main(int argc, char **argv)
// we need only one shared receiver decompressor for all recompressing streams
state.decompress = hd_rum_decompress_init(&state.mod, params.out_conf, params.capture_filter);
if(!state.decompress) {
return EXIT_FAIL_DECODER;
EXIT(EXIT_FAIL_DECODER);
}
for (i = 0; i < params.host_count; i++) {
@@ -795,7 +797,7 @@ int main(int argc, char **argv)
state.replicas[i] = new replica(params.hosts[i].addr, rx_port, tx_port, bufsize, &state.mod, params.hosts[i].force_ip_version);
} catch (string const &s) {
fputs(s.c_str(), stderr);
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
if(params.hosts[i].compression == NULL) {
@@ -816,7 +818,7 @@ int main(int argc, char **argv)
if(state.replicas[i]->recompress == 0) {
fprintf(stderr, "Initializing output port '%s' failed!\n",
params.hosts[i].addr);
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
// we don't care about this clients, we only tell decompressor to
// take care about them
@@ -827,7 +829,7 @@ int main(int argc, char **argv)
if (pthread_create(&thread, NULL, writer, (void *) &state)) {
fprintf(stderr, "cannot create writer thread\n");
return 2;
EXIT(2);
}
uint64_t received_data = 0;
@@ -884,7 +886,7 @@ int main(int argc, char **argv)
if (state.qtail->size < 0 && !should_exit) {
printf("read: %s\n", strerror(err));
return 2;
EXIT(2);
}
// pass poisoned pill to the worker
@@ -912,6 +914,8 @@ int main(int argc, char **argv)
qdestroy(state.queue);
common_cleanup(init);
printf("Exit\n");
return 0;

View File

@@ -63,11 +63,14 @@
#include <chrono>
#include <iomanip>
#include <iostream>
#include <list>
#include <set>
#include <sstream>
#ifdef HAVE_X
#if defined HAVE_X || defined BUILD_LIBRARIES
#include <dlfcn.h>
#endif
#if defined HAVE_X
#include <X11/Xlib.h>
/// @todo
/// The actual SONAME should be actually figured in configure.
@@ -108,8 +111,21 @@ std::unordered_map<std::string, std::string> commandline_params;
mainloop_t mainloop;
void *mainloop_udata;
static void common_cleanup()
struct init_data {
list <void *> opened_libs;
};
void common_cleanup(struct init_data *init)
{
if (init) {
#if defined BUILD_LIBRARIES
for (auto a : init->opened_libs) {
dlclose(a);
}
#endif
}
delete init;
#ifdef USE_MTRACE
muntrace();
#endif
@@ -165,8 +181,10 @@ static int x11_error_handler(Display *d, XErrorEvent *e) {
}
#endif
bool common_preinit(int argc, char *argv[])
struct init_data *common_preinit(int argc, char *argv[])
{
struct init_data *init;
uv_argc = argc;
uv_argv = argv;
@@ -205,16 +223,17 @@ bool common_preinit(int argc, char *argv[])
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(err != 0) {
fprintf(stderr, "WSAStartup failed with error %d.", err);
return false;
return nullptr;
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
fprintf(stderr, "Counld not found usable version of Winsock.\n");
WSACleanup();
return false;
return nullptr;
}
#endif
open_all("ultragrid_*.so"); // load modules
init = new init_data{};
open_all("ultragrid_*.so", init->opened_libs); // load modules
#ifdef USE_MTRACE
mtrace();
@@ -223,9 +242,7 @@ bool common_preinit(int argc, char *argv[])
perf_init();
perf_record(UVP_INIT, 0);
atexit(common_cleanup);
return true;
return init;
}
#include <sstream>

View File

@@ -131,7 +131,9 @@ void set_audio_delay(int val);
#define RATE_DEFAULT (-2)
#define RATE_FLAG_FIXED_RATE (1ll<<62ll) ///< use the bitrate as fixed, not capped
bool common_preinit(int argc, char *argv[]);
struct init_data;
struct init_data *common_preinit(int argc, char *argv[]);
void common_cleanup(struct init_data *init_data);
/**
* @param use_vidcap Use user suplied video capture device to elaborate input format.

View File

@@ -171,7 +171,7 @@ static int running_from_path(char * uv_argv[]) {
}
#endif
void open_all(const char *pattern) {
void open_all(const char *pattern, list<void *> &libs) {
#ifdef BUILD_LIBRARIES
char path[512];
glob_t glob_buf;
@@ -189,7 +189,8 @@ void open_all(const char *pattern) {
glob(path, 0, NULL, &glob_buf);
for(unsigned int i = 0; i < glob_buf.gl_pathc; ++i) {
if (!dlopen(glob_buf.gl_pathv[i], RTLD_NOW|RTLD_GLOBAL)) {
void *handle = dlopen(glob_buf.gl_pathv[i], RTLD_NOW|RTLD_GLOBAL);
if (!handle) {
char *error = dlerror();
verbose_msg("Library %s opening warning: %s \n", glob_buf.gl_pathv[i],
error);
@@ -197,7 +198,9 @@ void open_all(const char *pattern) {
if (filename && error) {
lib_errors.emplace(filename, error);
}
continue;
}
libs.push_back(handle);
}
globfree(&glob_buf);

View File

@@ -62,6 +62,11 @@
#endif /* BUILD_LIBRARIES */
#ifdef __cplusplus
#include <list>
void open_all(const char *pattern, std::list<void *> &libs);
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -78,7 +83,6 @@ enum library_class {
LIBRARY_CLASS_VIDEO_POSTPROCESS,
LIBRARY_CLASS_VIDEO_RXTX,
};
void open_all(const char *pattern);
const void *load_library(const char *name, enum library_class, int abi_version);
void register_library(const char *name, const void *info, enum library_class, int abi_version, int hidden);
void list_modules(enum library_class, int abi_version, bool full);

View File

@@ -589,8 +589,11 @@ static bool parse_params(char *optarg)
return true;
}
#define EXIT(retval) { common_cleanup(init); return retval; }
int main(int argc, char *argv[])
{
struct init_data *init = nullptr;
#if defined HAVE_SCHED_SETSCHEDULER && defined USE_RT
struct sched_param sp;
#endif
@@ -721,9 +724,9 @@ int main(int argc, char *argv[])
}
optind = 1;
if (!common_preinit(argc, argv)) {
if ((init = common_preinit(argc, argv)) == nullptr) {
log_msg(LOG_LEVEL_FATAL, "common_preinit() failed!\n");
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
struct state_uv uv{};
@@ -742,7 +745,7 @@ int main(int argc, char *argv[])
case 'd':
if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
list_video_display_devices(strcmp(optarg, "fullhelp") == 0);
return 0;
EXIT(0);
}
requested_display = optarg;
if(strchr(optarg, ':')) {
@@ -754,7 +757,7 @@ int main(int argc, char *argv[])
case 't':
if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
list_video_capture_devices(strcmp(optarg, "fullhelp") == 0);
return 0;
EXIT(0);
}
vidcap_params_set_device(vidcap_params_tail, optarg);
vidcap_params_tail = vidcap_params_allocate_next(vidcap_params_tail);
@@ -763,13 +766,13 @@ int main(int argc, char *argv[])
requested_mtu = atoi(optarg);
if (requested_mtu < 576 && optarg[strlen(optarg) - 1] != '!') {
log_msg(LOG_LEVEL_WARNING, "MTU %1$u seems to be too low, use \"%1$u!\" to force.\n", requested_mtu);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
break;
case 'M':
decoder_mode = get_video_mode_from_str(optarg);
if (decoder_mode == VIDEO_UNKNOWN) {
return strcasecmp(optarg, "help") == 0 ? EXIT_SUCCESS : EXIT_FAIL_USAGE;
EXIT(strcasecmp(optarg, "help") == 0 ? EXIT_SUCCESS : EXIT_FAIL_USAGE);
}
break;
case 'p':
@@ -777,11 +780,11 @@ int main(int argc, char *argv[])
break;
case 'v':
print_configuration();
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
case 'c':
if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
show_compress_help(strcmp(optarg, "fullhelp") == 0);
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
requested_compression = optarg;
break;
@@ -801,7 +804,7 @@ int main(int argc, char *argv[])
}
if (strcmp(audio_protocol, "help") == 0) {
printf("Audio protocol can be one of: " AUDIO_PROTOCOLS "\n");
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
break;
case OPT_VIDEO_PROTOCOL:
@@ -818,7 +821,7 @@ int main(int argc, char *argv[])
cout << "Specify a " << style::bold << "common" << style::reset << " protocol for both audio and video.\n";
cout << "Audio protocol can be one of: " << style::bold << AUDIO_PROTOCOLS "\n" << style::reset;
video_rxtx::list(strcmp(optarg, "fullhelp") == 0);
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
audio_protocol = video_protocol = optarg;
if (strchr(optarg, ':')) {
@@ -830,14 +833,14 @@ int main(int argc, char *argv[])
case 'r':
if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
audio_playback_help(strcmp(optarg, "full") == 0);
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
audio_recv = optarg;
break;
case 's':
if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
audio_capture_print_help(strcmp(optarg, "full") == 0);
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
audio_send = optarg;
break;
@@ -859,7 +862,7 @@ int main(int argc, char *argv[])
break;
case 'h':
usage(uv_argv[0], false);
return 0;
EXIT(0);
case 'P':
if(strchr(optarg, ':')) {
char *save_ptr = NULL;
@@ -872,7 +875,7 @@ int main(int argc, char *argv[])
audio_tx_port = atoi(tok);
} else {
usage(uv_argv[0]);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
}
} else {
@@ -881,10 +884,10 @@ int main(int argc, char *argv[])
break;
case 'l':
if (!parse_bitrate(optarg, &bitrate)) {
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
if (bitrate == RATE_DEFAULT) {
return EXIT_SUCCESS; // help written
EXIT(EXIT_SUCCESS); // help written
}
break;
case '4':
@@ -903,12 +906,12 @@ int main(int argc, char *argv[])
audio_capture_channels = atoi(optarg);
if (audio_capture_channels < 1 || audio_capture_channels > MAX_AUDIO_CAPTURE_CHANNELS) {
log_msg(LOG_LEVEL_ERROR, "Invalid number of channels %d!\n", audio_capture_channels);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
break;
case OPT_AUDIO_CAPTURE_FORMAT:
if (!parse_audio_capture_format(optarg)) {
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
break;
case OPT_ECHO_CANCELLATION:
@@ -916,7 +919,7 @@ int main(int argc, char *argv[])
break;
case OPT_FULLHELP:
usage(uv_argv[0], true);
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
case OPT_CUDA_DEVICE:
#ifdef HAVE_GPUJPEG
if(strcmp("help", optarg) == 0) {
@@ -926,9 +929,9 @@ int main(int argc, char *argv[])
if(ret == 0) {
module_done(CAST_MODULE(compression));
}
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
} else {
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
} else {
char *item, *save_ptr = NULL;
@@ -936,7 +939,7 @@ int main(int argc, char *argv[])
while((item = strtok_r(optarg, ",", &save_ptr))) {
if(i >= MAX_CUDA_DEVICES) {
fprintf(stderr, "Maximal number of CUDA device exceeded.\n");
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
cuda_devices[i] = atoi(item);
optarg = NULL;
@@ -947,7 +950,7 @@ int main(int argc, char *argv[])
break;
#else
fprintf(stderr, "CUDA support is not enabled!\n");
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
#endif // HAVE_CUDA
case OPT_MCAST_IF:
requested_mcast_if = optarg;
@@ -965,7 +968,7 @@ int main(int argc, char *argv[])
char dev_string[1024];
int ret;
if ((ret = playback_set_device(dev_string, sizeof dev_string, optarg)) <= 0) {
return ret == 0 ? EXIT_SUCCESS : EXIT_FAIL_USAGE;
EXIT(ret == 0 ? EXIT_SUCCESS : EXIT_FAIL_USAGE);
}
vidcap_params_set_device(vidcap_params_tail, dev_string);
vidcap_params_tail = vidcap_params_allocate_next(vidcap_params_tail);
@@ -974,11 +977,11 @@ int main(int argc, char *argv[])
case OPT_AUDIO_CODEC:
if(strcmp(optarg, "help") == 0) {
list_audio_codecs();
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
audio_codec = optarg;
if (!check_audio_codec(optarg)) {
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
break;
case OPT_CAPTURE_FILTER:
@@ -996,11 +999,11 @@ int main(int argc, char *argv[])
if(connection_type < 0 || connection_type > 1){
usage(uv_argv[0]);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
if ((tok = strtok_r(NULL, ":", &save_ptr))) {
usage(uv_argv[0]);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
} else {
control_port = atoi(optarg);
@@ -1023,25 +1026,25 @@ int main(int argc, char *argv[])
break;
case OPT_LIST_MODULES:
list_all_modules();
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
case OPT_START_PAUSED:
start_paused = true;
break;
case OPT_PARAM:
if (!parse_params(optarg)) {
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
}
break;
case OPT_PIX_FMTS:
print_pixel_formats();
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
case OPT_VIDEO_CODECS:
print_video_codecs();
return EXIT_SUCCESS;
EXIT(EXIT_SUCCESS);
case '?':
default:
usage(uv_argv[0]);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
}
@@ -1051,7 +1054,7 @@ int main(int argc, char *argv[])
if (argc > 1) {
log_msg(LOG_LEVEL_ERROR, "Multiple receivers given!\n");
usage(uv_argv[0]);
return EXIT_FAIL_USAGE;
EXIT(EXIT_FAIL_USAGE);
}
if (argc > 0) {
@@ -1181,12 +1184,12 @@ int main(int argc, char *argv[])
exporter = export_init(&uv.root_module, export_opts, should_export);
if (!exporter) {
log_msg(LOG_LEVEL_ERROR, "Export initialization failed.\n");
return EXIT_FAILURE;
EXIT(EXIT_FAILURE);
}
if (control_init(control_port, connection_type, &control, &uv.root_module, force_ip_version) != 0) {
LOG(LOG_LEVEL_FATAL) << "Error: Unable to initialize remote control!\n";
return EXIT_FAIL_CONTROL_SOCK;
EXIT(EXIT_FAIL_CONTROL_SOCK);
}
uv.audio = audio_cfg_init (&uv.root_module, audio_host, audio_rx_port,
@@ -1461,6 +1464,8 @@ cleanup:
signal(SIGABRT, SIG_IGN);
signal(SIGSEGV, SIG_IGN);
common_cleanup(init);
printf("Exit\n");
return exit_status;

View File

@@ -113,7 +113,7 @@ static void enqueue_all_finished_frames(struct vidcap_v4l2_state *s) {
}
}
static void common_cleanup(struct vidcap_v4l2_state *s) {
static void vidcap_v4l2_common_cleanup(struct vidcap_v4l2_state *s) {
if (!s) {
return;
}
@@ -759,7 +759,7 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
error:
free(tmp);
common_cleanup(s);
vidcap_v4l2_common_cleanup(s);
return VIDCAP_INIT_FAIL;
}
@@ -768,7 +768,7 @@ static void vidcap_v4l2_done(void *state)
{
struct vidcap_v4l2_state *s = (struct vidcap_v4l2_state *) state;
common_cleanup(s);
vidcap_v4l2_common_cleanup(s);
}
static void vidcap_v4l2_dispose_video_frame(struct video_frame *frame) {