Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Oct 2011 23:25:43 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Alexandr Matveev <timon@timon.net.nz>
Cc:        hackers@freebsd.org
Subject:   Re: sigprocmask and fork
Message-ID:  <20111026202542.GG50300@deviant.kiev.zoral.com.ua>
In-Reply-To: <4EA804C8.2030900@timon.net.nz>
References:  <4EA804C8.2030900@timon.net.nz>

next in thread | previous in thread | raw e-mail | index | archive | help

--8yqj9JR9W5krfwRp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Oct 26, 2011 at 05:02:00PM +0400, Alexandr Matveev wrote:
> Hi,
>=20
> We are using FreeBSD 8.2 on our servers for high load projects.
> When I was preparing system for production I saw strange (as I think)=20
> behavior,
> that leads to increased load on servers.
>=20
> If I made truss on httpd (apache22) process, I saw too much sigprocmask=
=20
> syscalls:
>=20
> 24822: sigprocmask(SIG_BLOCK,0x0,0x0)            =3D 0 (0x0)
> 24822: sigprocmask(SIG_BLOCK,0x0,0x0)            =3D 0 (0x0)
> 24822: sigprocmask(SIG_BLOCK,0x0,0x0)            =3D 0 (0x0)
> 24822: sigprocmask(SIG_BLOCK,0x0,0x0)            =3D 0 (0x0)
> 24822: sigprocmask(SIG_BLOCK,0x0,0x0)            =3D 0 (0x0)
> ... too many lines ...
>=20
> and
>=20
> 24822:
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|S=20
>=20
> IGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) =3D 0 (0x0)
> 24822: sigprocmask(SIG_SETMASK,0x0,0x0)          =3D 0 (0x0)
> 24822:
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|S=20
>=20
> IGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) =3D 0 (0x0)
> 24822: sigprocmask(SIG_SETMASK,0x0,0x0)          =3D 0 (0x0)
> 24822:
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|S=20
>=20
> IGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) =3D 0 (0x0)
> 24822: sigprocmask(SIG_SETMASK,0x0,0x0)          =3D 0 (0x0)
> ... too many lines ...
>=20
>=20
> but apache, and modules loaded from it do not call this directly.
> I was trying to use DTRACE for getting information about syscalls, and I
> got same result.
>=20
> I wrote a tiny sample
>=20
> code:
> $ cat sigproc_test.c
> #include<unistd.h>
>=20
> main()
> {
>         fork();
> }
> I ran it on FreeBSD with different compilers:
> $ cc sigproc_test.c -o sigproc_test
> $ truss ./sigproc_test 2>&1 | grep sigprocmask | wc -l
>        8
> $ g++ sigproc_test.c -o sigproc_test
> $ truss ./sigproc_test 2>&1 | grep sigprocmask | wc -l
>       20
>=20
> Is it normal to make so many sigprocmask syscalls for such simple program?
> For example, there is no sigprocmask syscalls when I run it on Debian=20
> Linux.
Yes, it is normal. I do not quite understand the relation between
"simple program" and "so many sigprocmask syscalls" claim, but alas.

The calls to sigprocmask originate from the rtld, which needs to
guarantee async-signal safety of the lazy binding process. The rtld
locks, besides other things, block signals. Also, due to an additional
requirement that rtld is functional after the fork, it has to acquire
the internal locks around fork in multithreaded programs.

All lock acquisions in the program which does only one fork(2) call
in main(), as well as in the program that does nothing in main at all,
come from the rtld initialization before main, and shared library
finalizations after. For empty main(), there are 4 locks acquisions
after return from main, so you get total 12 for forked version.

In essence, the trivial program makes the same amount of locking in
the startup/exit path, as non-trivial (the cost is proportional to the
number of shared libraries loaded).

The typical cause for the rtld locks acquisitions during the program
execution, besides the dlopen(3) activity, is the lazy resolution of
the PLT entries. LD_BIND_NOW=3D1 moves the load to the program startup.

>=20
> Another sample. Here we have sigprocmask syscalls on Linux too, but=20
> FreeBSD makes this syscall significantly more often:
> $ cat test.c
> #include<unistd.h>
>=20
> main()
> {
>     int i;
>     sleep(2);
>     for (i =3D 0; i<3; i++) {
>         int pid =3D fork();
>         if (!pid) {
>             sleep(0.5);
>             return 0;
>         }
>         sleep(2);
>     }
> }
>=20
> FreeBSD 8.2:
> # truss -f ./test
> ... SKIPPED ...
> 48666:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48666: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48666: __sysctl(0xbfbfe6a4,0x2,0x28192700,0xbfbfe6ac,0x0,0x0) =3D 0 (0x0)
> 48666:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48666: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48666: nanosleep({2.000000000 }) =3D 0 (0x0)
> 48666: fork() =3D 48667 (0xbe1b)
> 48667: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48667:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48667: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48667: process exit, rval =3D 0
> 48666: nanosleep({2.000000000 }) =3D 0 (0x0)
> 48666: fork() =3D 48669 (0xbe1d)
> 48669:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48669: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48669: process exit, rval =3D 0
> 48666: nanosleep({2.000000000 }) =3D 0 (0x0)
> 48666: fork() =3D 48674 (0xbe22)
> 48674: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48674:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48674: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48674: process exit, rval =3D 0
> 48666: nanosleep({2.000000000 }) =3D 0 (0x0)
> 48666:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48666: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48666:=20
> sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTE=
RM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIG=
XFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0)=20
> =3D 0 (0x0)
> 48666: sigprocmask(SIG_SETMASK,0x0,0x0) =3D 0 (0x0)
> 48666: process exit, rval =3D 0
>=20
> Linux:
> # strace ./test
> ... SKIPPED ...
> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) =3D 0
> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) =3D 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) =3D 0
> nanosleep({2, 0}, 0x7fff0e6b7050) =3D 0
> clone(child_stack=3D0,=20
> flags=3DCLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,=20
> child_tidptr=3D0x7fb553b0d9d0) =3D 24310
> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) =3D 0
> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) =3D 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) =3D 0
> --- SIGCHLD (Child exited) @ 0 (0) ---
> nanosleep({2, 0}, 0x7fff0e6b7050) =3D 0
> clone(child_stack=3D0,=20
> flags=3DCLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,=20
> child_tidptr=3D0x7fb553b0d9d0) =3D 24311
> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) =3D 0
> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) =3D 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) =3D 0
> --- SIGCHLD (Child exited) @ 0 (0) ---
> nanosleep({2, 0}, 0x7fff0e6b7050) =3D 0
> clone(child_stack=3D0,=20
> flags=3DCLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,=20
> child_tidptr=3D0x7fb553b0d9d0) =3D 24312
> rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) =3D 0
> rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) =3D 0
> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) =3D 0
> --- SIGCHLD (Child exited) @ 0 (0) ---
> nanosleep({2, 0}, 0x7fff0e6b7050) =3D 0
> exit_group(0) =3D ?
>=20
> --=20
> Alexander Matveev
> .masterhost
>=20
>=20
> _______________________________________________
> freebsd-hackers@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"

--8yqj9JR9W5krfwRp
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (FreeBSD)

iEYEARECAAYFAk6obMYACgkQC3+MBN1Mb4jt2QCg5Dvbl2nqUA/byNcicOzwwbuZ
+3kAoKfcHTYn7saxEK4111GSxUx1zV36
=qfbX
-----END PGP SIGNATURE-----

--8yqj9JR9W5krfwRp--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111026202542.GG50300>