File: control-server.c

package info (click to toggle)
syslog-ng 4.8.1-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 20,456 kB
  • sloc: ansic: 177,631; python: 13,035; cpp: 11,611; makefile: 7,012; sh: 5,147; java: 3,651; xml: 3,344; yacc: 1,377; lex: 599; perl: 193; awk: 190; objc: 162
file content (149 lines) | stat: -rw-r--r-- 4,692 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * Copyright (c) 2002-2014 Balabit
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As an additional exemption you are allowed to compile & link against the
 * OpenSSL libraries as published by the OpenSSL project. See the file
 * COPYING for details.
 *
 */

#include "control-server.h"
#include "control-connection.h"
#include "control-command-thread.h"
#include "messages.h"


void
_cancel_worker(gpointer data, gpointer user_data)
{
  ControlCommandThread *thread = (ControlCommandThread *) data;

  msg_warning("Requesting the cancellation of control command thread",
              evt_tag_str("control_command", control_command_thread_get_command(thread)));
  control_command_thread_cancel(thread);

  /* NOTE: threads would call control_server_worker_finished() when done (at
   * least if the main loop is still executing once to process our
   * thread_finished event).
   *
   * If finished() is called, our ref stored on the worker_threads list is
   * dropped at that point.
   *
   * If finished() is not called (e.g.  the workers are stuck and have not
   * exited until our mainloop exit strategy is executed), their reference
   * remains lingering on the worker_threads list.
   *
   * We try to take care of such lingering refs in control_server_stop(),
   * which is executed already after iv_main() returns.
   */
}

void
control_server_cancel_workers(ControlServer *self)
{
  if (self->worker_threads)
    {
      msg_debug("Cancelling control server worker threads");
      g_list_foreach(self->worker_threads, _cancel_worker, NULL);
      msg_debug("Control server worker threads have been cancelled");
    }
}

void
control_server_worker_started(ControlServer *self, ControlCommandThread *worker)
{
  control_command_thread_ref(worker);
  self->worker_threads = g_list_append(self->worker_threads, worker);
}

void
control_server_worker_finished(ControlServer *self, ControlCommandThread *worker)
{
  self->worker_threads = g_list_remove(self->worker_threads, worker);
  control_command_thread_unref(worker);
}

void
control_server_connection_closed(ControlServer *self, ControlConnection *cc)
{
  control_connection_stop_watches(cc);
  control_connection_unref(cc);
}

gboolean
control_server_start_method(ControlServer *self)
{
  /* NOTE: this is a placeholder and is empty for now.  Derived
   * ControlServer implementations must call this at startup */
  return TRUE;
}

void
_unref_worker(gpointer data)
{
  ControlCommandThread *thread = (ControlCommandThread *) data;

  msg_warning("Control command thread has not exited by the time we need to exit, forcing",
              evt_tag_str("control_command", control_command_thread_get_command(thread)));
  control_command_thread_unref(thread);
}

/* NOTE: this is called once the mainloop has exited, thus we would not get
 * our worker_thread_finished() callbacks anymore.  If our worker_threads is
 * not empty at this point, then they have not yet responded to our cancel
 * signal earlier and they won't as no further main loop iterations will be
 * performed.
 *
 * At this point we can unref the elements of the worker list, the thread
 * itself will keep a reference until it is done executing, but we won't get
 * notifications anymore.  If the thread is still running at the point
 * _exit() is called, we would leak some ControlCommandThread instances.
 */
void
control_server_stop_method(ControlServer *self)
{
  if (self->worker_threads)
    {
      g_list_free_full(self->worker_threads, _unref_worker);
      self->worker_threads = NULL;
    }
}

void
control_server_free_method(ControlServer *self)
{
}

void
control_server_init_instance(ControlServer *self)
{
  self->worker_threads = NULL;
  self->start = control_server_start_method;
  self->stop = control_server_stop_method;
  self->free_fn = control_server_free_method;
}

void
control_server_free(ControlServer *self)
{
  g_assert(self->worker_threads == NULL);
  if (self->free_fn)
    {
      self->free_fn(self);
    }
  g_free(self);
}