From e2beb7aa9900c650ec69594a2f26cc2889908134 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 16 May 2014 10:14:33 +0200 Subject: [PATCH 1/1] cleanup firewall service implementation We now run a separate server called 'pve-firewall' (renamed 'pvefw'). So service and management tool use the same name: # service pve-firewall start is the same as # pve-firewall start Also removed the read_pvefw_status/save_pvefw_status code. --- debian/pve-firewall.default | 2 + debian/pve-firewall.init | 75 ++++-- debian/rules | 2 +- debian/triggers | 1 + src/Makefile | 4 +- src/PVE/API2/Firewall/Groups.pm | 1 + src/PVE/Firewall.pm | 40 +--- src/pve-firewall | 412 ++++++++++++++++++++++++++++++++ src/pvefw | 242 ------------------- src/pvefw-logger.c | 3 +- 10 files changed, 472 insertions(+), 310 deletions(-) create mode 100644 debian/pve-firewall.default create mode 100644 debian/triggers create mode 100755 src/pve-firewall delete mode 100755 src/pvefw diff --git a/debian/pve-firewall.default b/debian/pve-firewall.default new file mode 100644 index 0000000..cc2818c --- /dev/null +++ b/debian/pve-firewall.default @@ -0,0 +1,2 @@ +# Should pve-firewall run automatically on startup? (default: yes) +START_FIREWALL=yes \ No newline at end of file diff --git a/debian/pve-firewall.init b/debian/pve-firewall.init index 5e01d1e..0c002a7 100755 --- a/debian/pve-firewall.init +++ b/debian/pve-firewall.init @@ -6,43 +6,66 @@ # Required-Stop: $remote_fs $network pvefw-logger pve-cluster # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: PVE firewall +# Short-Description: Proxmox VE firewall ### END INIT INFO . /lib/lsb/init-functions PATH=/sbin:/bin:/usr/bin:/usr/sbin -PVEFW=/usr/sbin/pvefw -NAME=pvefw -DESC="PVE firewall" -PIDFILE=/var/run/pvefw-logger.pid +NAME=pve-firewall +DAEMON=/usr/sbin/$NAME +DESC="Proxmox VE firewall" +PIDFILE=/var/run/$NAME.pid -test -f $PVEFW || exit 0 +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +START_FIREWALL=yes + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +[ "$START_FIREWALL" = "yes" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions # avoid warnings about uninstalled locales export LC_ALL="C" case "$1" in - start) - log_daemon_msg "Starting $DESC" "$NAME" - $PVEFW start - log_end_msg $? - ;; - stop) - log_daemon_msg "Stopping $DESC" "$NAME" - $PVEFW stop - log_end_msg $? - ;; - reload|restart|force-reload) - log_daemon_msg "Restarting $DESC" "$NAME" - $PVEFW update - log_end_msg $? - ;; - *) - N=/etc/init.d/$NAME - echo "Usage: $N {start|stop|restart|force-reload}" - exit 1 - ;; + start) + log_daemon_msg "Starting $DESC" "$NAME" + $DAEMON start + log_end_msg $? + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + $DAEMON stop + log_end_msg $? + ;; + status) + $DAEMON status + ;; + reload|restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + if ( [ -e $PIDFILE ] && kill -0 `cat $PIDFILE`) then + start-stop-daemon --stop --quiet --pidfile $PIDFILE --signal HUP + else + $DAEMON start + fi + log_end_msg $? + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|status|restart|force-reload}" + exit 1 + ;; esac exit 0 diff --git a/debian/rules b/debian/rules index 92e01c0..4fb0371 100755 --- a/debian/rules +++ b/debian/rules @@ -8,4 +8,4 @@ override_dh_installinit: dh_installinit -R -p pve-firewall - dh_installinit --name pvefw-logger + dh_installinit -R --name pvefw-logger diff --git a/debian/triggers b/debian/triggers new file mode 100644 index 0000000..90f5397 --- /dev/null +++ b/debian/triggers @@ -0,0 +1 @@ +interest /usr/share/perl5 diff --git a/src/Makefile b/src/Makefile index 590a783..364fd89 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,10 +19,10 @@ pvefw-logger: pvefw-logger.c $(shell pkg-config libnetfilter_log glib-2.0 gthread-2.0 --libs --cflags) .PHONY: install -install: pvefw pvefw-logger +install: pve-firewall pvefw-logger make -C PVE install install -d -m 0755 ${DESTDIR}/${SBINDIR} - install -m 0755 pvefw ${DESTDIR}/${SBINDIR} + install -m 0755 pve-firewall ${DESTDIR}/${SBINDIR} install -m 0755 --strip pvefw-logger ${DESTDIR}/${SBINDIR} .PHONY: clean diff --git a/src/PVE/API2/Firewall/Groups.pm b/src/PVE/API2/Firewall/Groups.pm index 442b4da..9e4d08a 100644 --- a/src/PVE/API2/Firewall/Groups.pm +++ b/src/PVE/API2/Firewall/Groups.pm @@ -38,6 +38,7 @@ __PACKAGE__->register_method({ description => "List security groups.", parameters => { additionalProperties => 0, + properties => {}, }, returns => { type => 'array', diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 946c9eb..be5354c 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -98,7 +98,6 @@ use Data::Dumper; my $nodename = PVE::INotify::nodename(); my $pve_fw_lock_filename = "/var/lock/pvefw.lck"; -my $pve_fw_status_filename = "/var/lib/pve-firewall/pvefw.status"; my $default_log_level = 'info'; @@ -2451,30 +2450,6 @@ sub round_powerof2 { return ++$int; } -sub save_pvefw_status { - my ($status) = @_; - - die "unknown status '$status' - internal error" - if $status !~ m/^(stopped|active)$/; - - mkdir dirname($pve_fw_status_filename); - PVE::Tools::file_set_contents($pve_fw_status_filename, $status); -} - -sub read_pvefw_status { - - my $status = 'unknown'; - - return 'stopped' if ! -f $pve_fw_status_filename; - - eval { - $status = PVE::Tools::file_get_contents($pve_fw_status_filename); - }; - warn $@ if $@; - - return $status; -} - sub load_clusterfw_conf { my ($filename) = @_; @@ -2969,7 +2944,7 @@ sub remove_pvefw_chains { } sub update { - my ($start, $verbose) = @_; + my ($verbose) = @_; my $code = sub { @@ -2978,9 +2953,7 @@ sub update { my $enable = $cluster_options->{enable}; - my $status = read_pvefw_status(); - - die "Firewall is disabled - cannot start\n" if !$enable && $start; + die "Firewall is disabled - cannot start\n" if !$enable; if (!$enable) { PVE::Firewall::remove_pvefw_chains(); @@ -2992,14 +2965,7 @@ sub update { my ($ruleset, $ipset_ruleset) = compile($cluster_conf, $hostfw_conf); - if ($start || $status eq 'active') { - - save_pvefw_status('active') if ($status ne 'active'); - - apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose); - } else { - print "Firewall not active (status = $status)\n" if $verbose; - } + apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose); }; run_locked($code); diff --git a/src/pve-firewall b/src/pve-firewall new file mode 100755 index 0000000..7de7355 --- /dev/null +++ b/src/pve-firewall @@ -0,0 +1,412 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use PVE::SafeSyslog; +use POSIX ":sys_wait_h"; +use Fcntl ':flock'; +use Getopt::Long; +use Time::HiRes qw (gettimeofday); +use PVE::Tools qw(dir_glob_foreach file_read_firstline); +use PVE::INotify; +use PVE::Cluster qw(cfs_read_file); +use PVE::RPCEnvironment; +use PVE::CLIHandler; +use PVE::Firewall; + +use base qw(PVE::CLIHandler); + +my $pve_firewall_pidfile = "/var/run/pve-firewall.pid"; + +$SIG{'__WARN__'} = sub { + my $err = $@; + my $t = $_[0]; + chomp $t; + print "$t\n"; + syslog('warning', "WARNING: %s", $t); + $@ = $err; +}; + +initlog('pve-firewall'); + +$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; + +die "please run as root\n" if $> != 0; + +PVE::INotify::inotify_init(); + +my $rpcenv = PVE::RPCEnvironment->init('cli'); + +$rpcenv->init_request(); +$rpcenv->set_language($ENV{LANG}); +$rpcenv->set_user('root@pam'); + +my $commandline = [$0, @ARGV]; + +$0 = "pve-firewall"; + +sub restart_server { + my ($waittime) = @_; + + syslog('info', "server shutdown (restart)"); + + $ENV{RESTART_PVE_FIREWALL} = 1; + + sleep($waittime) if $waittime; # avoid high server load due to restarts + + exec (@$commandline); + exit (-1); # never reached? +} + +sub cleanup { + unlink "$pve_firewall_pidfile.lock"; + unlink $pve_firewall_pidfile; +} + +sub lockpidfile { + my $pidfile = shift; + my $lkfn = "$pidfile.lock"; + + if (!open (FLCK, ">>$lkfn")) { + my $msg = "can't aquire lock on file '$lkfn' - $!"; + syslog ('err', $msg); + die "ERROR: $msg\n"; + } + + if (!flock (FLCK, LOCK_EX|LOCK_NB)) { + close (FLCK); + my $msg = "can't aquire lock '$lkfn' - $!"; + syslog ('err', $msg); + die "ERROR: $msg\n"; + } +} + +sub writepidfile { + my $pidfile = shift; + + if (!open (PIDFH, ">$pidfile")) { + my $msg = "can't open pid file '$pidfile' - $!"; + syslog ('err', $msg); + die "ERROR: $msg\n"; + } + print PIDFH "$$\n"; + close (PIDFH); +} + +my $restart_request = 0; +my $next_update = 0; + +my $cycle = 0; +my $updatetime = 10; + +my $initial_memory_usage; + +sub run_server { + my ($param) = @_; + + # try to get the lock + lockpidfile($pve_firewall_pidfile); + + # run in background + my $spid; + + my $restart = $ENV{RESTART_PVE_FIREWALL}; + + delete $ENV{RESTART_PVE_FIREWALL}; + + if (!$param->{debug}) { + open STDIN, '/dev/null' || die "can't write /dev/null"; + } + + if (!$restart && !$param->{debug}) { + $spid = fork(); + if (!defined ($spid)) { + my $msg = "can't put server into background - fork failed"; + syslog('err', $msg); + die "ERROR: $msg\n"; + } elsif ($spid) { # parent + exit (0); + } + } + + writepidfile($pve_firewall_pidfile); + + open STDERR, '>&STDOUT' || die "can't close STDERR\n"; + + $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = sub { + syslog('info' , "server closing"); + + $SIG{INT} = 'DEFAULT'; + + # wait for children + 1 while (waitpid(-1, POSIX::WNOHANG()) > 0); + + syslog('info' , "clear firewall rules"); + eval { PVE::Firewall::remove_pvefw_chains(); die "STOP";}; + warn $@ if $@; + + cleanup(); + + exit (0); + }; + + $SIG{HUP} = sub { + # wake up process, so this forces an immediate firewall rules update + syslog('info' , "received signal HUP (restart)"); + $restart_request = 1; + }; + + if ($restart) { + syslog('info' , "restarting server"); + } else { + syslog('info' , "starting server"); + } + + for (;;) { # forever + + eval { + + local $SIG{'__WARN__'} = 'IGNORE'; # do not fill up logs + + $next_update = time() + $updatetime; + + my ($ccsec, $cusec) = gettimeofday (); + eval { + PVE::Cluster::cfs_update(); + PVE::Firewall::update(); + }; + my $err = $@; + + if ($err) { + syslog('err', "status update error: $err"); + } + + my ($ccsec_end, $cusec_end) = gettimeofday (); + my $cptime = ($ccsec_end-$ccsec) + ($cusec_end - $cusec)/1000000; + + syslog('info', sprintf("firewall update time (%.3f seconds)", $cptime)) + if ($cptime > 5); + + $cycle++; + + my $mem = PVE::ProcFSTools::read_memory_usage(); + + if (!defined($initial_memory_usage) || ($cycle < 10)) { + $initial_memory_usage = $mem->{resident}; + } else { + my $diff = $mem->{resident} - $initial_memory_usage; + if ($diff > 5*1024*1024) { + syslog ('info', "restarting server after $cycle cycles to " . + "reduce memory usage (free $mem->{resident} ($diff) bytes)"); + restart_server(); + } + } + + my $wcount = 0; + while ((time() < $next_update) && + ($wcount < $updatetime) && # protect against time wrap + !$restart_request) { $wcount++; sleep (1); }; + + restart_server() if $restart_request; + }; + + my $err = $@; + + if ($err) { + syslog ('err', "ERROR: $err"); + restart_server(5); + exit (0); + } + } +} + +__PACKAGE__->register_method ({ + name => 'start', + path => 'start', + method => 'POST', + description => "Start the Proxmox VE firewall service.", + parameters => { + additionalProperties => 0, + properties => { + debug => { + description => "Debug mode - stay in foreground", + type => "boolean", + optional => 1, + default => 0, + }, + }, + }, + returns => { type => 'null' }, + + code => sub { + my ($param) = @_; + + run_server($param); + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'stop', + path => 'stop', + method => 'POST', + description => "Stop firewall. This will remove all rules installed by this script. The host is unprotected afterwards.", + parameters => { + additionalProperties => 0, + properties => {}, + }, + returns => { type => 'null' }, + + code => sub { + my ($param) = @_; + + my $pid = int(PVE::Tools::file_read_firstline($pve_firewall_pidfile) || 0); + + if ($pid) { + if (PVE::ProcFSTools::check_process_running($pid)) { + kill(15, $pid); # send TERM signal + # give max 5 seconds to shut down + for (my $i = 0; $i < 5; $i++) { + last if !PVE::ProcFSTools::check_process_running($pid); + sleep (1); + } + + # to be sure + kill(9, $pid); + waitpid($pid, 0); + } + if (-f $pve_firewall_pidfile) { + # try to get the lock + lockpidfile($pve_firewall_pidfile); + cleanup(); + } + } + + return undef; + }}); + +__PACKAGE__->register_method ({ + name => 'status', + path => 'status', + method => 'GET', + description => "Get firewall status.", + parameters => { + additionalProperties => 0, + properties => {}, + }, + returns => { + type => 'object', + additionalProperties => 0, + properties => { + status => { + type => 'string', + enum => ['unknown', 'stopped', 'active'], + }, + changes => { + description => "Set when there are pending changes.", + type => 'boolean', + optional => 1, + } + }, + }, + code => sub { + my ($param) = @_; + + local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog + + my $code = sub { + + my $pid = int(PVE::Tools::file_read_firstline($pve_firewall_pidfile) || 0); + my $running = PVE::ProcFSTools::check_process_running($pid); + + my $status = $running ? 'active' : 'stopped'; + + my $res = { status => $status }; + if ($status eq 'active') { + my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile(); + + my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset); + my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset); + + $res->{changes} = ($ipset_changes || $ruleset_changes) ? 1 : 0; + } + + return $res; + }; + + return PVE::Firewall::run_locked($code); + }}); + +__PACKAGE__->register_method ({ + name => 'compile', + path => 'compile', + method => 'POST', + description => "Compile amd print firewall rules. This is only for testing.", + parameters => { + additionalProperties => 0, + properties => {}, + }, + returns => { type => 'null' }, + + code => sub { + my ($param) = @_; + + local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog + + my $code = sub { + my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile(); + + my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, 1); + my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, 1); + if ($ipset_changes || $ruleset_changes) { + print "detected changes\n"; + } else { + print "no changes\n"; + } + }; + + PVE::Firewall::run_locked($code); + + return undef; + }}); + +my $nodename = PVE::INotify::nodename(); + +my $cmddef = { + start => [ __PACKAGE__, 'start', []], + stop => [ __PACKAGE__, 'stop', []], + compile => [ __PACKAGE__, 'compile', []], + status => [ __PACKAGE__, 'status', [], undef, sub { + my $res = shift; + if ($res->{changes}) { + print "Status: $res->{status} (pending changes)\n"; + } else { + print "Status: $res->{status}\n"; + } + }], + }; + +my $cmd = shift; + +PVE::CLIHandler::handle_cmd($cmddef, $0, $cmd, \@ARGV, undef, $0); + +exit (0); + +__END__ + +=head1 NAME + +pvestatd - PVE Firewall Daemon + +=head1 SYNOPSIS + +pve-firewall + +=head1 DESCRIPTION + +This service updates iptables rules periodically. + + + + diff --git a/src/pvefw b/src/pvefw deleted file mode 100755 index 754a4ea..0000000 --- a/src/pvefw +++ /dev/null @@ -1,242 +0,0 @@ -#!/usr/bin/perl -T - -use strict; -use warnings; - -use lib qw(.); -use PVE::Firewall; - -use PVE::SafeSyslog; -use PVE::Cluster; -use PVE::INotify; -use PVE::RPCEnvironment; - -use PVE::JSONSchema qw(get_standard_option); - -use PVE::CLIHandler; -use PVE::API2::Firewall::Groups; - -use base qw(PVE::CLIHandler); - -use Data::Dumper; - -$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; - -initlog ('pvefw'); - -die "please run as root\n" if $> != 0; - -PVE::INotify::inotify_init(); - -my $rpcenv = PVE::RPCEnvironment->init('cli'); - -$rpcenv->init_request(); -$rpcenv->set_language($ENV{LANG}); -$rpcenv->set_user('root@pam'); - -__PACKAGE__->register_method ({ - name => 'compile', - path => 'compile', - method => 'POST', - description => "Compile amd print firewall rules. This is only for testing.", - parameters => { - additionalProperties => 0, - properties => { - verbose => { - description => "Verbose output.", - type => "boolean", - optional => 1, - }, - }, - }, - returns => { type => 'null' }, - - code => sub { - my ($param) = @_; - - my $rpcenv = PVE::RPCEnvironment::get(); - - $param->{verbose} = 1 - if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli'); - - my $code = sub { - my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile(); - - if ($param->{verbose}) { - my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, 1); - my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, 1); - if ($ipset_changes || $ruleset_changes) { - print "detected changes\n"; - } else { - print "no changes\n"; - } - } - }; - - PVE::Firewall::run_locked($code); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'status', - path => 'status', - method => 'GET', - description => "Get firewall status.", - parameters => { - additionalProperties => 0, - properties => {}, - }, - returns => { - type => 'object', - additionalProperties => 0, - properties => { - status => { - type => 'string', - enum => ['unknown', 'stopped', 'active'], - }, - changes => { - description => "Set when there are pending changes.", - type => 'boolean', - optional => 1, - } - }, - }, - code => sub { - my ($param) = @_; - - my $rpcenv = PVE::RPCEnvironment::get(); - - $param->{verbose} = 1 - if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli'); - - my $code = sub { - my $status = PVE::Firewall::read_pvefw_status(); - - my $res = { status => $status }; - if ($status eq 'active') { - my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile(); - - my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset); - my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset); - # fixme: ipset changes - $res->{changes} = ($ipset_changes || $ruleset_changes) ? 1 : 0; - } - - return $res; - }; - - return PVE::Firewall::run_locked($code); - }}); - -__PACKAGE__->register_method ({ - name => 'start', - path => 'start', - method => 'POST', - description => "Start (or simply update if already active) firewall.", - parameters => { - additionalProperties => 0, - properties => { - verbose => { - description => "Verbose output.", - type => "boolean", - optional => 1, - default => 0, - }, - }, - }, - returns => { type => 'null' }, - - code => sub { - my ($param) = @_; - - PVE::Firewall::update(1, $param->{verbose}); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'update', - path => 'update', - method => 'POST', - description => "Check firewall rules. Then update the rules if the firewall is active.", - parameters => { - additionalProperties => 0, - properties => { - verbose => { - description => "Verbose output.", - type => "boolean", - optional => 1, - default => 0, - }, - }, - }, - returns => { type => 'null' }, - - code => sub { - my ($param) = @_; - - PVE::Firewall::update(0, $param->{verbose}); - - return undef; - }}); - -__PACKAGE__->register_method ({ - name => 'stop', - path => 'stop', - method => 'POST', - description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.", - parameters => { - additionalProperties => 0, - properties => {}, - }, - returns => { type => 'null' }, - - code => sub { - my ($param) = @_; - - my $code = sub { - PVE::Firewall::remove_pvefw_chains(); - PVE::Firewall::save_pvefw_status('stopped'); - }; - - PVE::Firewall::run_locked($code); - - return undef; - }}); - -my $nodename = PVE::INotify::nodename(); - -my $cmddef = { - compile => [ __PACKAGE__, 'compile', []], - start => [ __PACKAGE__, 'start', []], - update => [ __PACKAGE__, 'update', []], - status => [ __PACKAGE__, 'status', [], undef, sub { - my $res = shift; - if ($res->{changes}) { - print "Status: $res->{status} (pending changes)\n"; - } else { - print "Status: $res->{status}\n"; - } - }], - stop => [ __PACKAGE__, 'stop', []], - - # This is for debugging - listgroups => [ 'PVE::API2::Firewall::Groups', 'list', [], - { node => $nodename }, sub { - my $res = shift; - print Dumper($res); - }], - grouprules => [ 'PVE::API2::Firewall::Groups', 'get_rules', ['group'], - { node => $nodename }, sub { - my $res = shift; - print Dumper($res); - }], -}; - -my $cmd = shift; - -PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0); - -exit(0); - diff --git a/src/pvefw-logger.c b/src/pvefw-logger.c index 578d1aa..f4321fb 100644 --- a/src/pvefw-logger.c +++ b/src/pvefw-logger.c @@ -807,9 +807,8 @@ main(int argc, char *argv[]) g_io_add_watch(nflog_ch, G_IO_IN, nflog_read_cb, NULL); GIOChannel *sig_ch = g_io_channel_unix_new(sigfd); - printf("TEST0: %p %d\n", sig_ch, sigfd); if (!g_io_add_watch(sig_ch, G_IO_IN, signal_read_cb, NULL)) { - printf("TEST1\n"); exit(-1); + exit(-1); } GThread *wthread = g_thread_new("log_writer_thread", log_writer_thread, NULL); -- 2.39.2