运行时加载的共享库中的Libcurl和curl_global_init

运行时加载的共享库中的Libcurl和curl_global_init,c,thread-safety,libcurl,glib,C,Thread Safety,Libcurl,Glib,我正在开发一个photo booth应用程序,它使用3个模块来提供打印、捕获和触发功能。其想法是,人们可以为it开发扩展此功能的模块。这些模块实现为共享库,当用户单击“开始”时在运行时加载 我正在尝试实现一个打印机模块,“打印”到facebook图像库。我想用libcurl来做这个。我的问题是初始化函数:curl\u global\u init()。发件人: 此函数不是线程安全的。当程序中的任何其他线程(即共享相同内存的线程)正在运行时,不得调用此函数。这不仅仅意味着没有其他线程使用libcur

我正在开发一个photo booth应用程序,它使用3个模块来提供打印、捕获和触发功能。其想法是,人们可以为it开发扩展此功能的模块。这些模块实现为共享库,当用户单击“开始”时在运行时加载

我正在尝试实现一个打印机模块,“打印”到facebook图像库。我想用libcurl来做这个。我的问题是初始化函数:
curl\u global\u init()。发件人:

此函数不是线程安全的。当程序中的任何其他线程(即共享相同内存的线程)正在运行时,不得调用此函数。这不仅仅意味着没有其他线程使用libcurl。因为curl_global_init()调用其他类似线程不安全的库的函数,所以它可能与使用这些库的任何其他线程冲突

文件中说:

当为使用libcurl而编写的代码不是主程序,而是程序的模块化部分(例如,另一个库)时,全局常量情况值得特别考虑。作为一个模块,您的代码不知道程序的其他部分——它不知道它们是否使用libcurl。它的代码不一定在整个程序的开始和结束时运行

像这样的模块必须有自己的全局常量函数,就像curl\u global\u init()和curl\u global\u cleanup()一样。因此,模块在程序的开头和结尾都有控制权,并有一个调用libcurl函数的位置

…这似乎解决了这个问题。然而,这似乎意味着我的模块的
init()
finalize()
函数将在程序的开始和结束时被调用。由于模块设计为在运行时可交换,因此我无法做到这一点。即使我可以,我的应用程序也会使用GLib,根据它们的特性,假设没有线程运行是不安全的:

…从2.32版开始,GLib线程系统在程序开始时自动初始化,所有线程创建函数和同步原语都立即可用

请注意,即使您自己不调用g_thread_new(),假设您的程序没有线程也是不安全的。GLib和GIO可以并且将为自己的目的创建线程


我的问题是:有没有办法在我的应用程序中安全地调用
curl\u global\u init()
?我可以将对
curl\u global\u init()
curl\u global\u cleanup()
的调用放在模块的
init()和
finalize()函数中吗?我需要找到另一个HTTP库吗?

首先,如果没有这些限制,您将找不到任何其他库,因为libcurl从具有这些限制的第三方(主要是SSL)库继承了这些库。例如OpenSSL

这就是说,global_init的线程安全情况非常不幸,我们(在curl项目中)非常不喜欢这种情况,但只要我们使用其他库,我们就无能为力。这也意味着您的确切情况取决于构建libcurl时要使用的依赖库


在大多数情况下,按照您建议的方式从modules init()函数调用curl\u global\u init()会非常好。当然,我不能100%肯定地保证这是安全的,因为这里有一些我无法与之交谈的未知数。

谢谢你的回复。我一直在考虑从我的模块中派生一个进程,并出于其他原因让子进程处理实际工作,但我决定不这样做,而是选择一个更简单的解决方案。然而,在我看来,这可能是解决此问题的最安全的方法。@Chris注意,如果在多线程程序中使用fork(),则在成功执行execve()之前,不得调用任何异步信号不安全函数(即几乎任何函数)。您需要创建一个单独的可执行文件。