17
17
18
18
struct sigaction sigact ;
19
19
static gboolean first_iteration = TRUE;
20
+ static GMutex * mutex = NULL ;
21
+ static GAsyncQueue * queue = NULL ;
22
+ static volatile gboolean stop_signal = FALSE;
23
+ static GIOChannel * in = NULL ;
20
24
21
25
gint _list_compare (gconstpointer a , gconstpointer b ) {
22
26
gchar * ca = (gchar * ) a ;
23
27
gchar * cb = (gchar * ) b ;
24
28
return g_strcmp0 (cb , ca );
25
29
}
26
30
31
+ #define UNUSED (x ) (void)(x)
32
+
27
33
void clean_too_old_files () {
28
34
gchar * dirpath = g_path_get_dirname (log_file );
29
35
GDir * dir = g_dir_open (dirpath , 0 , NULL );
@@ -92,12 +98,11 @@ gboolean rotate() {
92
98
93
99
void signal_handler (int signum ) {
94
100
if ((signum == SIGTERM ) || (signum == SIGTERM )) {
95
- // nice exit to execute exit_handler
96
- exit (0 );
101
+ stop_signal = TRUE;
97
102
}
98
103
}
99
104
100
- static void every_second (int sig ) {
105
+ static void every_second () {
101
106
int fd = lock_control_file (log_file );
102
107
if (fd >= 0 ) {
103
108
if (first_iteration ) {
@@ -111,19 +116,11 @@ static void every_second(int sig) {
111
116
destroy_output_channel ();
112
117
init_output_channel (log_file , use_locks , TRUE, chmod_str , chown_str , chgrp_str );
113
118
unlock_control_file (fd );
114
- if (sig > 0 ) {
115
- // if sig<0, this is the final call before program end
116
- alarm (1 );
117
- }
118
119
return ;
119
120
}
120
121
glong size = get_file_size (log_file );
121
122
if (size < 0 ) {
122
123
unlock_control_file (fd );
123
- if (sig > 0 ) {
124
- // if sig<0, this is the final call before program end
125
- alarm (1 );
126
- }
127
124
return ;
128
125
}
129
126
gboolean must_rotate = FALSE;
@@ -149,18 +146,53 @@ static void every_second(int sig) {
149
146
}
150
147
unlock_control_file (fd );
151
148
}
152
- if (sig > 0 ) {
153
- // if sig<0, this is the final call before program end
154
- alarm (1 );
149
+ }
150
+
151
+ gpointer stop_thread (gpointer data ) {
152
+ // we do this here and not in signal_handler to avoid malloc in signal
153
+ // handlers
154
+ UNUSED (data );
155
+ while (stop_signal == FALSE) {
156
+ sleep (1 );
155
157
}
158
+ g_async_queue_push (queue , GINT_TO_POINTER (2 ));
159
+ return NULL ;
156
160
}
157
161
158
- void init_every_second_signal () {
159
- sigact .sa_handler = every_second ;
160
- sigemptyset (& sigact .sa_mask );
161
- sigact .sa_flags = 0 ;
162
- sigaction (SIGALRM , & sigact , (struct sigaction * )NULL );
163
- alarm (1 );
162
+ gpointer management_thread (gpointer data ) {
163
+ gpointer qdata ;
164
+ GTimeVal tval ;
165
+ gint stop_flag = 0 ;
166
+ UNUSED (data );
167
+ while (TRUE) {
168
+ g_get_current_time (& tval );
169
+ g_time_val_add (& tval , 1000000 );
170
+ qdata = g_async_queue_timed_pop (queue , & tval );
171
+ if (qdata != NULL ) {
172
+ stop_flag = GPOINTER_TO_INT (qdata );
173
+ }
174
+ g_mutex_lock (mutex );
175
+ every_second ();
176
+ g_mutex_unlock (mutex );
177
+ if (qdata != NULL ) {
178
+ break ;
179
+ }
180
+ }
181
+ if (stop_flag == 2 ) {
182
+ // in this case (sigterm), we prefer to keep the mutex
183
+ g_mutex_lock (mutex );
184
+ }
185
+ destroy_output_channel ();
186
+ if (rm_fifo_at_exit == TRUE) {
187
+ if (fifo != NULL ) {
188
+ g_unlink (fifo );
189
+ }
190
+ }
191
+ if (stop_flag == 2 ) {
192
+ // we exit here for sigterm as main thread is blocked in reading
193
+ exit (0 );
194
+ }
195
+ return NULL ;
164
196
}
165
197
166
198
void init_or_reinit_output_channel (const gchar * lg_file , gboolean us_locks ) {
@@ -174,14 +206,6 @@ void init_or_reinit_output_channel(const gchar *lg_file, gboolean us_locks) {
174
206
unlock_control_file (lock_fd );
175
207
}
176
208
177
- void exit_handler () {
178
- if (rm_fifo_at_exit == TRUE) {
179
- if (fifo != NULL ) {
180
- g_unlink (fifo );
181
- }
182
- }
183
- }
184
-
185
209
int main (int argc , char * argv [])
186
210
{
187
211
GOptionContext * context ;
@@ -198,7 +222,9 @@ int main(int argc, char *argv[])
198
222
g_print ("%s" , g_option_context_get_help (context , TRUE, NULL ));
199
223
exit (1 );
200
224
}
201
- atexit (exit_handler );
225
+ g_thread_init (NULL );
226
+ mutex = g_mutex_new ();
227
+ queue = g_async_queue_new ();
202
228
signal (SIGTERM , signal_handler );
203
229
signal (SIGINT , signal_handler );
204
230
set_default_values_from_env ();
@@ -212,7 +238,6 @@ int main(int argc, char *argv[])
212
238
}
213
239
}
214
240
g_free (log_dir );
215
- GIOChannel * in = NULL ;
216
241
if (fifo == NULL ) {
217
242
// We read from stdin
218
243
in = g_io_channel_unix_new (fileno (stdin ));
@@ -228,30 +253,34 @@ int main(int argc, char *argv[])
228
253
GIOStatus in_status = G_IO_STATUS_NORMAL ;
229
254
GString * in_buffer = g_string_new (NULL );
230
255
init_or_reinit_output_channel (log_file , use_locks );
231
- init_every_second_signal ();
256
+ g_thread_create (stop_thread , NULL , FALSE, NULL );
257
+ GThread * management = g_thread_create (management_thread , NULL , TRUE, NULL );
232
258
while ((in_status != G_IO_STATUS_EOF ) && (in_status != G_IO_STATUS_ERROR )) {
233
259
in_status = g_io_channel_read_line_string (in , in_buffer , NULL , NULL );
234
260
if (in_status == G_IO_STATUS_NORMAL ) {
261
+ g_mutex_lock (mutex );
235
262
while (TRUE) {
236
263
gboolean write_status = write_output_channel (in_buffer );
237
264
if (write_status == FALSE) {
238
265
g_warning ("error during write on: %s" , log_file );
239
- alarm (0 ); // to avoid a potential deadlock with SIGALARM every_second() calls
240
266
init_or_reinit_output_channel (log_file , use_locks );
241
- alarm (1 );
242
267
continue ;
243
268
}
244
269
break ;
245
270
}
271
+ g_mutex_unlock (mutex );
246
272
}
247
273
}
248
- alarm (0 ); // to avoid a potential deadlock with SIGALARM every_second() calls
249
- every_second (-1 );
250
- destroy_output_channel ();
274
+ // if we are here, the "in" input channel is closed
275
+ signal (SIGINT , SIG_DFL );
276
+ signal (SIGTERM , SIG_DFL );
277
+ g_async_queue_push (queue , GINT_TO_POINTER (1 ));
278
+ g_thread_join (management );
251
279
g_io_channel_shutdown (in , FALSE, NULL );
252
280
g_io_channel_unref (in );
253
281
g_string_free (in_buffer , TRUE);
254
282
g_option_context_free (context );
255
283
g_free (log_file );
284
+ g_mutex_free (mutex );
256
285
return 0 ;
257
286
}
0 commit comments