Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Dec 2018 22:00:56 -0800
From:      Conrad Meyer <cem@freebsd.org>
To:        andrew@ziglang.org
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>
Subject:   Re: raise() implementation in freebsd libc vs musl libc
Message-ID:  <CAG6CVpVGfL3Fu4DMyuzPa02Ud=cr1-kkDpkmpb_psjYrczMoaA@mail.gmail.com>
In-Reply-To: <70c7214e-3619-115d-abca-09853a1729a6@ziglang.org>
References:  <70c7214e-3619-115d-abca-09853a1729a6@ziglang.org>

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

The musl signal blocking dates to this commit:

https://git.musl-libc.org/cgit/musl/commit/?id=0bed7e0acfd34e3fb63ca0e4d99b7592571355a9

The concern raised in that commit was that raise(3) could
theoretically be interrupted by a concurrently running signal handler
which invokes fork() (also sighandler-safe), resulting in
inconsistent/stale values from gettid(2)/getpid(2) on Linux (at the
time).

On both systems, gettid(2) / thr_self(2) returns a unique thread
identifier that cannot be reused until the thread it identifies has
exited.  So, I don't know.  I guess if fork happens between thr_self()
and thr_kill(), the parent process may have already exited and had its
tid recycled by the time the child process invokes thr_kill().

OTOH, that seems like a pretty byzantine / broken application?  I'm
not sure it's libc's job to prevent applications from shooting
themselves in the foot.  Forking in a signal handler is already
somewhat dicey, and especially so if the child does not immediately
exec() or _exit(2).

Anyway, that's just my guess.  I am not a libthr expert on either BSD
nor Linux, so take this with a big grain of salt.  Signals were a
mistake ;-).

Best,
Conrad

P.S., Zig looks quite promising, I am excited to see where it goes.


On Wed, Dec 12, 2018 at 9:12 PM Andrew Kelley <andrew@ziglang.org> wrote:
>
> Howdy,
>
> I noticed that musl-libc blocks signals in raise() to prevent a race
> condition, but freebsd libc does not. is there a reason it's necessary
> on linux and not freebsd?
>
> musl
> int raise(int sig)
> {
>         sigset_t set;
>         __block_app_sigs(&set);
>         int ret = syscall(SYS_tkill, __pthread_self()->tid, sig);
>         __restore_sigs(&set);
>         return ret;
> }
>
> freebsd
> int
> __raise(int s)
> {
>         long id;
>
>         if (__sys_thr_self(&id) == -1)
>                 return (-1);
>         return (__sys_thr_kill(id, s));
> }
>
> Regards,
> Andrew
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAG6CVpVGfL3Fu4DMyuzPa02Ud=cr1-kkDpkmpb_psjYrczMoaA>