Deadlock in rr_workpool.c/process_item when calling g_thread_create
Sandro Poppi <[email protected]> Sat, 31 May 2003 15:41:57 +0200
| Newsgroups | gmane.network.beep.roadrunner.general |
|---|---|
| Message-ID | <[email protected]> |
Hi,
I'm still running into a deadlock situation in our snort plugin where I
can't find an answer. I cut it down to the following line in
rr_workpool.c, function process_item:
-------------------------------------------------------------------------
static void
process_item (RRWorkPool *pool)
{
GError *error = NULL;
WorkItem *item;
g_return_if_fail (pool);
if ((item = get_next_item (pool))) {
pool->num_threads++;
==> if (g_thread_create (work_proxy, item, FALSE, &error) == NULL)
{
g_error ("g_thread_create failed: %s\n",
error->message);
}
}
}
-------------------------------------------------------------------------
I get no message, I also added an else statement to print something to
stderr but it didn't show up either. g_thread_create is called and then
the listening server (see below) hangs with 100% cpu.
What's even worse is that after some 5 - 10 minutes the first run is ok
but the second and all further calls hang except waiting some more
minutes. Very strange.
Here is a code snippet where the IDXP/TLS connection is established
(removed all the ugly debugging statements ;):
-------------------------------------------------------------------------
static gchar *
keyfile_resolver (RRTLS *tls)
{
return g_strdup (global_data->own_prv_key);
}
static gchar *
certfile_resolver (RRTLS *tls)
{
return g_strdup (global_data->own_cert);
}
static gboolean
enableTls (RRConnection *connection)
{
GError *error = NULL;
RRTLSConfig *cfg;
cfg = rr_tls_config_new ();
rr_tls_config_set_key_resolver (cfg, keyfile_resolver);
rr_tls_config_set_cert_resolver (cfg, certfile_resolver);
rr_tls_config_set_trusted_ca_file (cfg, global_data->ca_cert);
if (!rr_tls_privatize (connection, global_data->name, cfg, &error)) {
g_print ("rr_tls_privatize failed: %s\n", error->message);
return FALSE;
}
rr_tls_config_destroy (cfg);
if (rr_tls_is_strong_enough (connection, 128)) {
}
else {
g_print ("The encryption is not strong enough!\n");
return FALSE;
}
if (rr_tls_is_trusted (connection, &error)) {
}
else {
g_print ("Certificate verification failed: '%s'!\n",
error->message);
return FALSE;
}
return TRUE;
}
static RRConnection *
initIdxpConnection (IDMEFOutputFacility * facility)
{
RRProfileRegistry *profreg;
RRManager *manager;
RRConnection *conn;
GError *error = NULL;
RRIDXPConfig *idxpconfig = NULL;
/* FIXME: define prio/stream */
idxpconfig = rr_idxp_config_new_with_vals (TM_URI, RR_IDXP_ROLE_CLIENT,
global_data->name,NULL,
RR_IDXP_CHANNEL_PRIORITY_UNDEFINED, TRUE,
RR_IDXP_STREAM_UNDEFINED, FALSE);
/* save config for later use */
facility->config->idxp_config.RRIdxpConfig = idxpconfig;
/* Tell roadrunner which profiles we want to support */
profreg = rr_profile_registry_new ();
rr_profile_registry_add_profile (profreg, RR_TYPE_TLS, NULL);
rr_profile_registry_add_profile (profreg, RR_TYPE_IDXP, idxpconfig);
/* Create a connection object */
if ((conn = rr_tcp_connection_new (profreg,
facility->config->idxp_config.age_host,
facility->config->idxp_config.port_num,
&error)) == NULL)
FatalError ("IDMEF::initIdxpConnection: rr_tcp_connection_new failed:
%s\n", error->message);
/* Check if the remote peer supports the profiles we need */
g_assert (rr_connection_peer_supports_profile (conn, RR_TYPE_IDXP));
g_assert (rr_connection_peer_supports_profile (conn, /* require TLS or
exit */
if (!enableTls (conn))
{
g_print ("IDMEF::initIdxpConnection: TLS connection not
established!\n");
return NULL;
}
manager = rr_connection_get_manager (conn);
return conn;
}
void OpenFacilityIdxp(IDMEFOutputFacility * facility)
{
... some snort specific stuff ...
if (!(conn = initIdxpConnection (facility)))
{
FatalError ("IDMEF::OpenFacilityIdxp: initIdxpConnection failed.
Exiting ...\n");
}
manager = rr_connection_get_manager (conn);
/* save connection information */
facility->state->idxp_state.rrconnection = conn;
}
-------------------------------------------------------------------------
And here is the listening server's code:
-------------------------------------------------------------------------
#include <librr/rr.h>
#include <librrtls/rr-tls.h>
#include <librridxp/rridxp.h>
static gchar *
tls_keyfile_resolver (RRTLS *tls)
{
RRConnection *connection = RR_CHANNEL (tls)->connection;
const gchar *server_name = rr_connection_get_server_name
(connection);
rr_debug1 ("resolver: server_name = '%s'\n", server_name);
/* The server_name can be used to select different files for
* different "virtual hosts". */
return g_strdup ("./server.key");
}
static gchar *
tls_certfile_resolver (RRTLS *tls)
{
return g_strdup ("./server.crt");
}
gboolean idxp_consumer (RRIDXP *idxp, RRIDXPMessageType msg_type,
RRFrame *frame,
gpointer user_data, GError **error)
{
g_print ("yay!\n");
return TRUE;
}
int
main (gint argc, gchar **argv)
{
GError *error = NULL;
RRListener *listener;
RRProfileRegistry *profreg;
RRTLSConfig *tls_config;
RRIDXPConfig *idxp_config = NULL;
idxp_config = rr_idxp_config_new_with_vals
("http://idxp.codefactory.se/idxp",
RR_IDXP_ROLE_SERVER,
"pluto", NULL,
RR_IDXP_CHANNEL_PRIORITY_UNDEFINED,
TRUE,
RR_IDXP_STREAM_UNDEFINED, FALSE);
rr_idxp_config_set_frame_handler (idxp_config,
RR_IDXP_MESSAGE_TEXT,
idxp_consumer, NULL, TRUE);
rr_idxp_config_set_frame_handler (idxp_config,
RR_IDXP_MESSAGE_IDMEF,
idxp_consumer, NULL, TRUE);
tls_config = rr_tls_config_new ();
rr_tls_config_set_key_resolver (tls_config,
tls_keyfile_resolver);
rr_tls_config_set_cert_resolver (tls_config,
tls_certfile_resolver);
if (!rr_init (&argc, &argv, &error))
g_error ("rr_init failed: %s\n", error->message);
profreg = rr_profile_registry_new ();
rr_profile_registry_add_profile (profreg, RR_TYPE_TLS, tls_config);
rr_profile_registry_add_profile (profreg, RR_TYPE_IDXP,
idxp_config);
if ((listener = rr_tcp_listener_new (profreg, "localhost", 10289,
&error)) == NULL)
g_error ("listen failed: %s\n", error->message);
if (!rr_wait_until_done (&error))
g_error ("rr_run failed: %s\n", error->message);
if (!rr_listener_shutdown (listener, &error))
g_error ("rr_listener_shutdown failed: %s\n",
error->message);
if (!rr_exit (&error))
g_error ("rr_exit failed: %s\n", error->message);
rr_tls_config_destroy (tls_config);
rr_idxp_config_destroy (idxp_config);
return 0;
}
-------------------------------------------------------------------------
Tested with glib-2.0.1 (shipped with RH) and 2.0.7 (created RPM myself)
and kernel-2.4.18-27.7.x (shipped with RH) on Redhat 7.3.
Any hint is greatly appreciated!
TIA,
Sandro
--
"Linux is like a wigwam: no windows, no gates ... apache inside!"
http://spoppi.home.pages.de/
http://www.lug-burghausen.org/