Skip to content

Commit

Permalink
Filed doesn't respond to first connection after start.
Browse files Browse the repository at this point in the history
The setup of the thread specific key is flawed. In essence
its setup twice (once via the init_msg() call and once
via the pthread_once call in jcr.c). This new code fixes
that by:

- Setup thread specific data key only once.
- Use pthread_key_create_once_np when available.
  This is a non portable but cleaner implementation of
  both a pthread_once() and a pthread_key_create().
- For Windows use a workaround around pthread_once() as that
  seems to hang for unknown reason. Now we use a boolean
  protected by an mutex to make sure the setup is only done once.

Fixes #210: Filed doesn't respond to first connection after start.
  • Loading branch information
Marco van Wieringen committed Feb 17, 2015
1 parent 8d83aaf commit 0f62233
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 12 deletions.
62 changes: 53 additions & 9 deletions src/lib/jcr.c
Expand Up @@ -75,8 +75,18 @@ static dlist *jcrs = NULL; /* JCR chain */
static pthread_mutex_t jcr_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t job_start_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t last_jobs_mutex = PTHREAD_MUTEX_INITIALIZER;

#ifdef HAVE_WIN32
static bool tsd_initialized = false;
static pthread_key_t jcr_key; /* Pointer to jcr for each thread */
#else
#ifdef PTHREAD_ONCE_KEY_NP
static pthread_key_t jcr_key = PTHREAD_ONCE_KEY_NP;
#else
static pthread_key_t jcr_key; /* Pointer to jcr for each thread */
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
#endif
#endif

static char Job_status[] = "Status Job=%s JobStatus=%d\n";

Expand Down Expand Up @@ -312,18 +322,51 @@ static void job_end_pop(JCR *jcr)
}

/*
* Create thread key for thread specific data
* Create thread key for thread specific data.
*/
void create_jcr_key()
static void create_jcr_key()
{
int status = pthread_key_create(&jcr_key, NULL);
int status;

#ifdef PTHREAD_ONCE_KEY_NP
status = pthread_key_create_once_np(&jcr_key, NULL);
#else
status = pthread_key_create(&jcr_key, NULL);
#endif
if (status != 0) {
berrno be;
Jmsg1(NULL, M_ABORT, 0, _("pthread key create failed: ERR=%s\n"),
be.bstrerror(status));
}
}

/*
* Setup thread key for thread specific data.
*/
void setup_tsd_key()
{
#ifdef HAVE_WIN32
P(jcr_lock);
if (!tsd_initialized) {
create_jcr_key();
tsd_initialized = true;
}
V(jcr_lock);
#else
#ifdef PTHREAD_ONCE_KEY_NP
create_jcr_key();
#else
int status;

status = pthread_once(&key_once, create_jcr_key);
if (status != 0) {
berrno be;
Jmsg1(NULL, M_ABORT, 0, _("pthread_once failed. ERR=%s\n"), be.bstrerror(status));
}
#endif
#endif
}

/*
* Create a Job Control Record and link it into JCR chain
* Returns newly allocated JCR
Expand All @@ -339,11 +382,9 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
int status;

Dmsg0(dbglvl, "Enter new_jcr\n");
status = pthread_once(&key_once, create_jcr_key);
if (status != 0) {
berrno be;
Jmsg1(NULL, M_ABORT, 0, _("pthread_once failed. ERR=%s\n"), be.bstrerror(status));
}

setup_tsd_key();

jcr = (JCR *)malloc(size);
memset(jcr, 0, size);
jcr->msg_queue = New(dlist(item, &item->link));
Expand All @@ -352,6 +393,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
Jmsg(NULL, M_ABORT, 0, _("Could not init msg_queue mutex. ERR=%s\n"),
be.bstrerror(status));
}

jcr->job_end_push.init(1, false);
jcr->sched_time = time(NULL);
jcr->initial_sched_time = jcr->sched_time;
Expand Down Expand Up @@ -634,7 +676,9 @@ void JCR::set_killable(bool killable)
*/
void set_jcr_in_tsd(JCR *jcr)
{
int status = pthread_setspecific(jcr_key, (void *)jcr);
int status;

status = pthread_setspecific(jcr_key, (void *)jcr);
if (status != 0) {
berrno be;
Jmsg1(jcr, M_ABORT, 0, _("pthread_setspecific failed: ERR=%s\n"),
Expand Down
6 changes: 3 additions & 3 deletions src/lib/message.c
Expand Up @@ -63,7 +63,7 @@ job_code_callback_t message_job_code_callback = NULL; /* Job code callback. Only
/* Forward referenced functions */

/* Imported functions */
void create_jcr_key();
void setup_tsd_key();

/* Static storage */

Expand Down Expand Up @@ -270,10 +270,10 @@ void init_msg(JCR *jcr, MSGSRES *msg, job_code_callback_t job_code_callback)
if (jcr == NULL && msg == NULL) {
init_last_jobs_list();
/*
* Create a daemon key then set invalid jcr
* Setup a daemon key then set invalid jcr
* Maybe we should give the daemon a jcr???
*/
create_jcr_key();
setup_tsd_key();
set_jcr_in_tsd(INVALID_JCR);
}

Expand Down

0 comments on commit 0f62233

Please sign in to comment.