public inbox for libc-help@sourceware.org
 help / color / mirror / Atom feed
* determine whether code is running in a signal handler context
@ 2017-10-18 14:18 Yubin Ruan
  2017-10-18 18:34 ` Carlos O'Donell
                   ` (4 more replies)
  0 siblings, 5 replies; 31+ messages in thread
From: Yubin Ruan @ 2017-10-18 14:18 UTC (permalink / raw)
  To: libc-help

Hi,

I am writing to see if this is any util functions in libc that can
help to determine it is currently running in a signal.

I wrote some library and provide a function which will be used in many
client code. However this function is not async-signal safe (it calls
malloc(3)) so when it is called, I want to detect whether it is
currently running in a signal handler. If it is, I can avoid calling
those not-async-signal-safe functions which might cause deadlock.

that is, I want a `in_signal_handler_context()' utility that can be
used as this:

int mylibfunc( void ) {
    if( in_signal_handler_context() ) { return(-1) }
    // rest of function goes here
    return( 0 );
}


Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
@ 2017-10-18 18:34 ` Carlos O'Donell
  2017-10-19  1:52   ` Yubin Ruan
  2017-10-19  2:59 ` Sean Conner
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-18 18:34 UTC (permalink / raw)
  To: Yubin Ruan, libc-help

On 10/18/2017 07:18 AM, Yubin Ruan wrote:
> Hi,
> 
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
> 
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.
> 
> that is, I want a `in_signal_handler_context()' utility that can be
> used as this:
> 
> int mylibfunc( void ) {
>     if( in_signal_handler_context() ) { return(-1) }
>     // rest of function goes here
>     return( 0 );
> }
 
Only (b).

(a) The kernel knows, but doesn't tell you.

(b) Only via architecture-specific checks which involve inspecting the
    call frame to determine if there is a signal frame on the stack.

(c) glibc *could* know, but it probably needs kernel help for other
    purposes.

This issue was discussed orthogonality here:
https://sourceware.org/ml/libc-alpha/2014-02/msg00798.html

Where glibc would create a wrapper for all signal handlers to save and
restore errno to work around bugs in signal handlers that modify errno.

There is no solution yet.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 18:34 ` Carlos O'Donell
@ 2017-10-19  1:52   ` Yubin Ruan
  2017-10-19  2:19     ` Carlos O'Donell
  0 siblings, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-10-19  1:52 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-help

2017-10-19 2:34 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
> On 10/18/2017 07:18 AM, Yubin Ruan wrote:
>> Hi,
>>
>> I am writing to see if this is any util functions in libc that can
>> help to determine it is currently running in a signal.
>>
>> I wrote some library and provide a function which will be used in many
>> client code. However this function is not async-signal safe (it calls
>> malloc(3)) so when it is called, I want to detect whether it is
>> currently running in a signal handler. If it is, I can avoid calling
>> those not-async-signal-safe functions which might cause deadlock.
>>
>> that is, I want a `in_signal_handler_context()' utility that can be
>> used as this:
>>
>> int mylibfunc( void ) {
>>     if( in_signal_handler_context() ) { return(-1) }
>>     // rest of function goes here
>>     return( 0 );
>> }
>
> Only (b).
>
> (a) The kernel knows, but doesn't tell you.
>
> (b) Only via architecture-specific checks which involve inspecting the
>     call frame to determine if there is a signal frame on the stack.

Is (b) deterministic? How can we know whether a call frame is a signal
frame and how can we know at which point we should stop when
inspecting the frame?

Somebody pointed out that on Linux all signal handlers are called from
vdso, so I come up with the following code to "inspect" the call frame
and see whether there is any address which points at some place inside
the VDSO:

===============================
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>

#include <unistd.h>

uintmax_t vdso_start = 0;
uintmax_t vdso_end = 0;         /* actually, next byte */

int check_stack_for_vdso(uint64_t rsp, size_t len)
{
    size_t i;
    /* printf("rsp = %jx\n", rsp); */

    for (i = 0; i < len; i++, rsp++) {
        /* printf("*rsp is: %jx\n", *(uint64_t *)rsp); */
        if ((*(uint64_t *)rsp) >= vdso_start && (*(uint64_t *)rsp) < vdso_end)
                return 1;
    }

    return 0;
}

void handler(int signo)
{
    uint64_t rsp;

    __asm__ __volatile__ ("movq %%rsp, %0" : "=r"(rsp));
    /* XXX only for demonstration, don't call printf from a signal handler */
    printf("handler: check_stack_for_vdso() = %d\n",
check_stack_for_vdso(rsp, 200));
    /* I am hoping that `check_stack_for_vdso()' here would return 1.
     * But that is not the case */
}

void parse_maps()
{
    FILE *maps;
    char buf[256];
    char path[7];
    uintmax_t start, end, offset, inode;
    char r, w, x, p;
    unsigned major, minor;

    maps = fopen("/proc/self/maps", "rt");
    if (maps == NULL)
        return;

    while (!feof(maps) && !ferror(maps)) {
        if (fgets(buf, 256, maps) != NULL) {
                if (sscanf(buf, "%jx-%jx %c%c%c%c %jx %u:%u %ju %6s",
                                &start, &end, &r, &w, &x, &p, &offset,
                                &major, &minor, &inode, path) == 11) {
                        if (!strcmp(path, "[vdso]")) {
                                vdso_start = start;
                                vdso_end = end;
                                break;
                        }
                }
        }
    }

    fclose(maps);

    printf("[vdso] at %jx-%jx\n", vdso_start, vdso_end);
}

int main()
{
    struct sigaction sa;
    uint64_t rsp;

    parse_maps();
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESTART;

    if (sigaction(SIGUSR1, &sa, NULL) < 0) {
        perror("sigaction");
        exit(1);
    }

    __asm__ __volatile__ ("movq %%rsp, %0" : "=r"(rsp));
    printf("before kill: check_stack_for_vdso() = %d\n",
check_stack_for_vdso(rsp, 200));

    kill(getpid(), SIGUSR1);

    __asm__ __volatile__ ("movq %%rsp, %0" : "=r"(rsp));
    printf("after kill: check_stack_for_vdso() = %d\n",
check_stack_for_vdso(rsp, 200));

    return 0;
}
==============================================

I am using a 64 bit Linux. I try to go back 200 step long when inside
a signal handler, but I cannot find any address inside the vdso area.

(sorry if the code above get auto-wrapped by the mail agent)

Yubin

[1]: https://stackoverflow.com/questions/4832743/howto-determine-if-code-is-running-in-signal-handler-context
(I use some of its code)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  1:52   ` Yubin Ruan
@ 2017-10-19  2:19     ` Carlos O'Donell
  2017-10-19  2:39       ` Will Hawkins
  2017-10-19  4:01       ` Yubin Ruan
  0 siblings, 2 replies; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-19  2:19 UTC (permalink / raw)
  To: Yubin Ruan; +Cc: libc-help

On 10/18/2017 06:52 PM, Yubin Ruan wrote:
> 2017-10-19 2:34 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
>> On 10/18/2017 07:18 AM, Yubin Ruan wrote:
>>> Hi,
>>>
>>> I am writing to see if this is any util functions in libc that can
>>> help to determine it is currently running in a signal.
>>>
>>> I wrote some library and provide a function which will be used in many
>>> client code. However this function is not async-signal safe (it calls
>>> malloc(3)) so when it is called, I want to detect whether it is
>>> currently running in a signal handler. If it is, I can avoid calling
>>> those not-async-signal-safe functions which might cause deadlock.
>>>
>>> that is, I want a `in_signal_handler_context()' utility that can be
>>> used as this:
>>>
>>> int mylibfunc( void ) {
>>>     if( in_signal_handler_context() ) { return(-1) }
>>>     // rest of function goes here
>>>     return( 0 );
>>> }
>>
>> Only (b).
>>
>> (a) The kernel knows, but doesn't tell you.
>>
>> (b) Only via architecture-specific checks which involve inspecting the
>>     call frame to determine if there is a signal frame on the stack.
> 
> Is (b) deterministic? How can we know whether a call frame is a signal
> frame and how can we know at which point we should stop when
> inspecting the frame?

We could spend days talking about this. The answer should be deterministic,
and gdb solves it, but the solution involves some heuristic checks, and
unwinding (a complex topic).

> Somebody pointed out that on Linux all signal handlers are called from
> vdso, so I come up with the following code to "inspect" the call frame
> and see whether there is any address which points at some place inside
> the VDSO:

This is not true. It is architecture dependent. For examples on how complex
it is to get this 100% right you have to go read gdb sources to see how
they do this. It is non-trivial. It might be easier to use a library like
libunwind to determine this for you (if it even can).

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  2:19     ` Carlos O'Donell
@ 2017-10-19  2:39       ` Will Hawkins
  2017-10-19  3:12         ` Carlos O'Donell
  2017-10-19  4:01       ` Yubin Ruan
  1 sibling, 1 reply; 31+ messages in thread
From: Will Hawkins @ 2017-10-19  2:39 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Yubin Ruan, libc-help

On Wednesday, October 18, 2017, Carlos O'Donell <carlos@redhat.com> wrote:

> On 10/18/2017 06:52 PM, Yubin Ruan wrote:
> > 2017-10-19 2:34 GMT+08:00 Carlos O'Donell <carlos@redhat.com
> <javascript:;>>:
> >> On 10/18/2017 07:18 AM, Yubin Ruan wrote:
> >>> Hi,
> >>>
> >>> I am writing to see if this is any util functions in libc that can
> >>> help to determine it is currently running in a signal.
> >>>
> >>> I wrote some library and provide a function which will be used in many
> >>> client code. However this function is not async-signal safe (it calls
> >>> malloc(3)) so when it is called, I want to detect whether it is
> >>> currently running in a signal handler. If it is, I can avoid calling
> >>> those not-async-signal-safe functions which might cause deadlock.
> >>>
> >>> that is, I want a `in_signal_handler_context()' utility that can be
> >>> used as this:
> >>>
> >>> int mylibfunc( void ) {
> >>>     if( in_signal_handler_context() ) { return(-1) }
> >>>     // rest of function goes here
> >>>     return( 0 );
> >>> }
> >>
> >> Only (b).
> >>
> >> (a) The kernel knows, but doesn't tell you.
> >>
> >> (b) Only via architecture-specific checks which involve inspecting the
> >>     call frame to determine if there is a signal frame on the stack.
> >
> > Is (b) deterministic? How can we know whether a call frame is a signal
> > frame and how can we know at which point we should stop when
> > inspecting the frame?
>
> We could spend days talking about this. The answer should be deterministic,
> and gdb solves it, but the solution involves some heuristic checks, and
> unwinding (a complex topic).
>
> > Somebody pointed out that on Linux all signal handlers are called from
> > vdso, so I come up with the following code to "inspect" the call frame
> > and see whether there is any address which points at some place inside
> > the VDSO:
>
> This is not true. It is architecture dependent. For examples on how complex
> it is to get this 100% right you have to go read gdb sources to see how
> they do this. It is non-trivial. It might be easier to use a library like
> libunwind to determine this for you (if it even can).


This is a fascinating thread. The downside to using libunwind is that,
iirc, it requires debugging information in the binary to work. In other
words, it would not work on a stripped binary. Please correct me if I am
wrong.

Thanks for the discussion!
Will



>
> --
> Cheers,
> Carlos.
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
  2017-10-18 18:34 ` Carlos O'Donell
@ 2017-10-19  2:59 ` Sean Conner
  2017-10-19  3:12 ` Sean Conner
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 31+ messages in thread
From: Sean Conner @ 2017-10-19  2:59 UTC (permalink / raw)
  To: libc-help

It was thus said that the Great Yubin Ruan once stated:
> Hi,
> 
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
> 
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.

  Wouldn't it be easier to just document (in as large a font as you care to)
that none of the functions in your library can be used in a signal handler,
and if they are, it's "undefined behavior"?

  -spc

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  2:39       ` Will Hawkins
@ 2017-10-19  3:12         ` Carlos O'Donell
  2017-10-19  4:07           ` Yubin Ruan
  2017-10-19  4:19           ` Will Hawkins
  0 siblings, 2 replies; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-19  3:12 UTC (permalink / raw)
  To: Will Hawkins; +Cc: Yubin Ruan, libc-help

On 10/18/2017 07:39 PM, Will Hawkins wrote:
>> This is not true. It is architecture dependent. For examples on how complex
>> it is to get this 100% right you have to go read gdb sources to see how
>> they do this. It is non-trivial. It might be easier to use a library like
>> libunwind to determine this for you (if it even can).
> 
> This is a fascinating thread. The downside to using libunwind is that,
> iirc, it requires debugging information in the binary to work. In other
> words, it would not work on a stripped binary. Please correct me if I am
> wrong.

No. libunwind only needs .eh_frame/.debug_frame, not debug information.

Some unwinders can operate without debug information, but only if the
architecture, and ABI layout of the frame allow unwinding with a frame
pointer. On 32-bit ARM, at least for a while, the frame pointer was
synthesized by the compiler to avoid using a fixed frame pointer and
free up such a pointer for the compiler to use. The side effect is that
you always need the DWARF unwind information to unwind a frame, but you
do *not* need debug information. One should be careful not to confuse
the two. The generic term "debug information" can mean a lot more,
including all the DWARF required to debug the program. You don't need
this to unwind, you only need .eh_frame/.debug_frame. As you see 32-bit
ARM was leading the charge here to free up a register for compiler use,
and now it's common practice on x86_64 and x86 to compile without the
frame pointer, and so you must have auxiliary information to unwind,
and you can't write a by-hand unwinder that follows the frame pointer.

The complex part is that to unwind from an asynchronously delivered signal
you need asynchronous unwind tables which describe how to unwind from
any point in the program, because when the signal arrives you may attempt
an unwind from any point to an outer frame. Usually the unwind information
can be elided to the point at which function calls are made, or try/catch
blocks.

But you need not unwind from the signal handler, you need only detect
that you are *in* a signal handler, and libunwind might have enough
heuristics for the machines you care about that it might work. I have
not tried it though, so YMMV.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
  2017-10-18 18:34 ` Carlos O'Donell
  2017-10-19  2:59 ` Sean Conner
@ 2017-10-19  3:12 ` Sean Conner
  2017-10-19  3:51   ` Yubin Ruan
  2017-10-20 10:32 ` Szabolcs Nagy
  2017-11-27  8:43 ` Yubin Ruan
  4 siblings, 1 reply; 31+ messages in thread
From: Sean Conner @ 2017-10-19  3:12 UTC (permalink / raw)
  To: libc-help

It was thus said that the Great Yubin Ruan once stated:
> Hi,
> 
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
> 
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.

  Wouldn't it be easier (and safer) just to document the library as
not-async-signal-safe ("These functions, called from a signal handler, will
invoke undefined behavior")?  Use a large font if you have to, but I think
protecting programmers from themselves over the long term is bad.

  -spc

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  3:12 ` Sean Conner
@ 2017-10-19  3:51   ` Yubin Ruan
  2017-10-19  7:10     ` Jeffrey Walton
  0 siblings, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-10-19  3:51 UTC (permalink / raw)
  To: Sean Conner; +Cc: libc-help

2017-10-19 11:12 GMT+08:00 Sean Conner <sean@conman.org>:
> It was thus said that the Great Yubin Ruan once stated:
>> Hi,
>>
>> I am writing to see if this is any util functions in libc that can
>> help to determine it is currently running in a signal.
>>
>> I wrote some library and provide a function which will be used in many
>> client code. However this function is not async-signal safe (it calls
>> malloc(3)) so when it is called, I want to detect whether it is
>> currently running in a signal handler. If it is, I can avoid calling
>> those not-async-signal-safe functions which might cause deadlock.
>
>   Wouldn't it be easier (and safer) just to document the library as
> not-async-signal-safe ("These functions, called from a signal handler, will
> invoke undefined behavior")?  Use a large font if you have to, but I think
> protecting programmers from themselves over the long term is bad.

Yes I can document that and that is indeed an option. But I don't know
whether the user will read the docs. ;-)

It would be great if we can handle that smoothly such that users will
not notice.

Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  2:19     ` Carlos O'Donell
  2017-10-19  2:39       ` Will Hawkins
@ 2017-10-19  4:01       ` Yubin Ruan
  1 sibling, 0 replies; 31+ messages in thread
From: Yubin Ruan @ 2017-10-19  4:01 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-help

Hi Carlos,

2017-10-19 10:19 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
> On 10/18/2017 06:52 PM, Yubin Ruan wrote:
>> 2017-10-19 2:34 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
>>> On 10/18/2017 07:18 AM, Yubin Ruan wrote:
>>>> Hi,
>>>>
>>>> I am writing to see if this is any util functions in libc that can
>>>> help to determine it is currently running in a signal.
>>>>
>>>> I wrote some library and provide a function which will be used in many
>>>> client code. However this function is not async-signal safe (it calls
>>>> malloc(3)) so when it is called, I want to detect whether it is
>>>> currently running in a signal handler. If it is, I can avoid calling
>>>> those not-async-signal-safe functions which might cause deadlock.
>>>>
>>>> that is, I want a `in_signal_handler_context()' utility that can be
>>>> used as this:
>>>>
>>>> int mylibfunc( void ) {
>>>>     if( in_signal_handler_context() ) { return(-1) }
>>>>     // rest of function goes here
>>>>     return( 0 );
>>>> }
>>>
>>> Only (b).
>>>
>>> (a) The kernel knows, but doesn't tell you.
>>>
>>> (b) Only via architecture-specific checks which involve inspecting the
>>>     call frame to determine if there is a signal frame on the stack.
>>
>> Is (b) deterministic? How can we know whether a call frame is a signal
>> frame and how can we know at which point we should stop when
>> inspecting the frame?
>
> We could spend days talking about this. The answer should be deterministic,
> and gdb solves it, but the solution involves some heuristic checks, and
> unwinding (a complex topic).

So I think I am going to talk with some gdb people some more.

>> Somebody pointed out that on Linux all signal handlers are called from
>> vdso, so I come up with the following code to "inspect" the call frame
>> and see whether there is any address which points at some place inside
>> the VDSO:
>
> This is not true. It is architecture dependent. For examples on how complex
> it is to get this 100% right you have to go read gdb sources to see how
> they do this. It is non-trivial. It might be easier to use a library like
> libunwind to determine this for you (if it even can).

Will it be better if we can limit the architecture to X86/64?

Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  3:12         ` Carlos O'Donell
@ 2017-10-19  4:07           ` Yubin Ruan
  2017-10-19  4:56             ` Carlos O'Donell
  2017-10-19  4:19           ` Will Hawkins
  1 sibling, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-10-19  4:07 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Will Hawkins, libc-help

2017-10-19 11:12 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
> On 10/18/2017 07:39 PM, Will Hawkins wrote:
>>> This is not true. It is architecture dependent. For examples on how complex
>>> it is to get this 100% right you have to go read gdb sources to see how
>>> they do this. It is non-trivial. It might be easier to use a library like
>>> libunwind to determine this for you (if it even can).
>>
>> This is a fascinating thread. The downside to using libunwind is that,
>> iirc, it requires debugging information in the binary to work. In other
>> words, it would not work on a stripped binary. Please correct me if I am
>> wrong.
>
> No. libunwind only needs .eh_frame/.debug_frame, not debug information.
>
> Some unwinders can operate without debug information, but only if the
> architecture, and ABI layout of the frame allow unwinding with a frame
> pointer. On 32-bit ARM, at least for a while, the frame pointer was
> synthesized by the compiler to avoid using a fixed frame pointer and
> free up such a pointer for the compiler to use. The side effect is that
> you always need the DWARF unwind information to unwind a frame, but you
> do *not* need debug information. One should be careful not to confuse
> the two. The generic term "debug information" can mean a lot more,
> including all the DWARF required to debug the program. You don't need
> this to unwind, you only need .eh_frame/.debug_frame. As you see 32-bit
> ARM was leading the charge here to free up a register for compiler use,
> and now it's common practice on x86_64 and x86 to compile without the
> frame pointer, and so you must have auxiliary information to unwind,
> and you can't write a by-hand unwinder that follows the frame pointer.

By "auxiliary information", do you mean those auxiliary information
provided by the kernel (to the dynamic loader), e.g., environment
variables, or what? It seems to me that if we have the frame pointers,
it would be a lot easier. And it would be better if we limit our code
to X86/64.

> The complex part is that to unwind from an asynchronously delivered signal
> you need asynchronous unwind tables which describe how to unwind from
> any point in the program, because when the signal arrives you may attempt
> an unwind from any point to an outer frame. Usually the unwind information
> can be elided to the point at which function calls are made, or try/catch
> blocks.

Agree. That is why I think checking the stack "by hand" for addresses
in VDSO is not deterministic.

> But you need not unwind from the signal handler, you need only detect
> that you are *in* a signal handler, and libunwind might have enough

Yes. I should have emphasized that I need only detect that the code is
*in* a signal handler, and that is all I want. So if anyone can
provide more info/heuristic about that (just about that) I will be
very thankful.

Yubin

> heuristics for the machines you care about that it might work. I have
> not tried it though, so YMMV.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  3:12         ` Carlos O'Donell
  2017-10-19  4:07           ` Yubin Ruan
@ 2017-10-19  4:19           ` Will Hawkins
  1 sibling, 0 replies; 31+ messages in thread
From: Will Hawkins @ 2017-10-19  4:19 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Yubin Ruan, libc-help

On Wed, Oct 18, 2017 at 11:12 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 10/18/2017 07:39 PM, Will Hawkins wrote:
>>> This is not true. It is architecture dependent. For examples on how complex
>>> it is to get this 100% right you have to go read gdb sources to see how
>>> they do this. It is non-trivial. It might be easier to use a library like
>>> libunwind to determine this for you (if it even can).
>>
>> This is a fascinating thread. The downside to using libunwind is that,
>> iirc, it requires debugging information in the binary to work. In other
>> words, it would not work on a stripped binary. Please correct me if I am
>> wrong.
>
> No. libunwind only needs .eh_frame/.debug_frame, not debug information.

You are obviously correct. I am sorry for being misleading in my
statement. I spoke broadly of debug information when that's not what I
meant precisely. Thank you for your correction and the additional
information that you provided. Very interesting!

Will

>
> Some unwinders can operate without debug information, but only if the
> architecture, and ABI layout of the frame allow unwinding with a frame
> pointer. On 32-bit ARM, at least for a while, the frame pointer was
> synthesized by the compiler to avoid using a fixed frame pointer and
> free up such a pointer for the compiler to use. The side effect is that
> you always need the DWARF unwind information to unwind a frame, but you
> do *not* need debug information. One should be careful not to confuse
> the two. The generic term "debug information" can mean a lot more,
> including all the DWARF required to debug the program. You don't need
> this to unwind, you only need .eh_frame/.debug_frame. As you see 32-bit
> ARM was leading the charge here to free up a register for compiler use,
> and now it's common practice on x86_64 and x86 to compile without the
> frame pointer, and so you must have auxiliary information to unwind,
> and you can't write a by-hand unwinder that follows the frame pointer.
>
> The complex part is that to unwind from an asynchronously delivered signal
> you need asynchronous unwind tables which describe how to unwind from
> any point in the program, because when the signal arrives you may attempt
> an unwind from any point to an outer frame. Usually the unwind information
> can be elided to the point at which function calls are made, or try/catch
> blocks.
>
> But you need not unwind from the signal handler, you need only detect
> that you are *in* a signal handler, and libunwind might have enough
> heuristics for the machines you care about that it might work. I have
> not tried it though, so YMMV.
>
> --
> Cheers,
> Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  4:07           ` Yubin Ruan
@ 2017-10-19  4:56             ` Carlos O'Donell
  0 siblings, 0 replies; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-19  4:56 UTC (permalink / raw)
  To: Yubin Ruan; +Cc: Will Hawkins, libc-help

On 10/18/2017 09:07 PM, Yubin Ruan wrote:
> By "auxiliary information", do you mean those auxiliary information
> provided by the kernel (to the dynamic loader), e.g., environment
> variables, or what? It seems to me that if we have the frame pointers,
> it would be a lot easier. And it would be better if we limit our code
> to X86/64.

No, by 'auxiliary information' I mean .eh_frame/.debug_frame, the information
that tells you where the current frame's data is located (on stack or in
registers), so you can, from your current IP, find enough data to attempt
a frame unwind.

> Yes. I should have emphasized that I need only detect that the code is
> *in* a signal handler, and that is all I want. So if anyone can
> provide more info/heuristic about that (just about that) I will be
> very thankful.

You have to do architecture specific things, which I don't have immediately
off the top of my head.

gdb has a architecture-specific signal call recognizer:

gdb/gdb/i386-linux-tdep.c:
  71 /* Recognizing signal handler frames.  */
  72 
  73 /* GNU/Linux has two flavors of signals.  Normal signal handlers, and
  74    "realtime" (RT) signals.  The RT signals can provide additional
  75    information to the signal handler if the SA_SIGINFO flag is set
  76    when establishing a signal handler using `sigaction'.  It is not
  77    unlikely that future versions of GNU/Linux will support SA_SIGINFO
  78    for normal signals too.  */
...

gdb/gdb/aarch64-linux-tdep.c:
  49 /* Signal frame handling.
  50 
  51       +------------+  ^
  52       | saved lr   |  |
  53    +->| saved fp   |--+
  54    |  |            |
  55    |  |            |
  56    |  +------------+
  57    |  | saved lr   |
  58    +--| saved fp   |
  59    ^  |            |
  60    |  |            |
  61    |  +------------+
  62    ^  |            |
  63    |  | signal     |
  64    |  |            |        SIGTRAMP_FRAME (struct rt_sigframe)
  65    |  | saved regs |
  66    +--| saved sp   |--> interrupted_sp
  67    |  | saved pc   |--> interrupted_pc
  68    |  |            |
  69    |  +------------+
  70    |  | saved lr   |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
  71    +--| saved fp   |<- FP
  72       |            |         NORMAL_FRAME
  73       |            |<- SP
  74       +------------+
  75 
  76   On signal delivery, the kernel will create a signal handler stack
  77   frame and setup the return address in LR to point at restorer stub.
  78   The signal stack frame is defined by:
....

And so on and so forth...

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-19  3:51   ` Yubin Ruan
@ 2017-10-19  7:10     ` Jeffrey Walton
  0 siblings, 0 replies; 31+ messages in thread
From: Jeffrey Walton @ 2017-10-19  7:10 UTC (permalink / raw)
  To: Yubin Ruan; +Cc: libc-help

On Wed, Oct 18, 2017 at 11:51 PM, Yubin Ruan <ablacktshirt@gmail.com> wrote:
> 2017-10-19 11:12 GMT+08:00 Sean Conner <sean@conman.org>:
>> ...
>>   Wouldn't it be easier (and safer) just to document the library as
>> not-async-signal-safe ("These functions, called from a signal handler, will
>> invoke undefined behavior")?  Use a large font if you have to, but I think
>> protecting programmers from themselves over the long term is bad.
>
> Yes I can document that and that is indeed an option. But I don't know
> whether the user will read the docs. ;-)
>
> It would be great if we can handle that smoothly such that users will
> not notice.

If RTFM was going to work, then it would have happened in the last 50
years or so.

You're applying solid engineering techniques. I encourage you to stay
the course.

Jeff

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
                   ` (2 preceding siblings ...)
  2017-10-19  3:12 ` Sean Conner
@ 2017-10-20 10:32 ` Szabolcs Nagy
  2017-10-20 11:23   ` Yubin Ruan
  2017-11-27  8:43 ` Yubin Ruan
  4 siblings, 1 reply; 31+ messages in thread
From: Szabolcs Nagy @ 2017-10-20 10:32 UTC (permalink / raw)
  To: Yubin Ruan, libc-help; +Cc: nd

On 18/10/17 15:18, Yubin Ruan wrote:
> Hi,
> 
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
> 
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.
> 

note that in posix as-safety is symmetric between the
interrupted code and interrupt handler: if any of the
interrupt and interrupt handler is as-safe then the
behaviour is well defined.

so calling non-as-safe code in an asynchronous signal
handler is perfectly fine if the interrupted code is
as-safe.

there are synchronous signals too, i.e. raise(sig),
and then the signal handler runs in well-defined state
(one can use signal masks to make sure a signal handler
only runs in such state)

so using "in_signal_handler_context()" is not a valid
way to verify the as-safety interface contract.

> that is, I want a `in_signal_handler_context()' utility that can be
> used as this:
> 
> int mylibfunc( void ) {
>     if( in_signal_handler_context() ) { return(-1) }
>     // rest of function goes here
>     return( 0 );
> }
> 
> 
> Yubin
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-20 10:32 ` Szabolcs Nagy
@ 2017-10-20 11:23   ` Yubin Ruan
  2017-10-20 11:31     ` Szabolcs Nagy
  0 siblings, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-10-20 11:23 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: libc-help, nd

Thanks Szabolcs,

2017-10-20 18:32 GMT+08:00 Szabolcs Nagy <szabolcs.nagy@arm.com>:
> On 18/10/17 15:18, Yubin Ruan wrote:
>> Hi,
>>
>> I am writing to see if this is any util functions in libc that can
>> help to determine it is currently running in a signal.
>>
>> I wrote some library and provide a function which will be used in many
>> client code. However this function is not async-signal safe (it calls
>> malloc(3)) so when it is called, I want to detect whether it is
>> currently running in a signal handler. If it is, I can avoid calling
>> those not-async-signal-safe functions which might cause deadlock.
>>
>
> note that in posix as-safety is symmetric between the
> interrupted code and interrupt handler: if any of the
> interrupt and interrupt handler is as-safe then the
> behaviour is well defined.
>
> so calling non-as-safe code in an asynchronous signal
> handler is perfectly fine if the interrupted code is
> as-safe.
>
> there are synchronous signals too, i.e. raise(sig),
> and then the signal handler runs in well-defined state
> (one can use signal masks to make sure a signal handler
> only runs in such state)

Actually I think the point is that that piece of code should not run
in a signal handler. That have nothing to do with sync-signal or
async-signal code, because in both case we might encounter deadlock.
From this perspective, that `in_signal_handler_context()' make sense
to me.

Yubin

> so using "in_signal_handler_context()" is not a valid
> way to verify the as-safety interface contract.
>
>> that is, I want a `in_signal_handler_context()' utility that can be
>> used as this:
>>
>> int mylibfunc( void ) {
>>     if( in_signal_handler_context() ) { return(-1) }
>>     // rest of function goes here
>>     return( 0 );
>> }
>>
>>
>> Yubin
>>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-20 11:23   ` Yubin Ruan
@ 2017-10-20 11:31     ` Szabolcs Nagy
  2017-10-20 17:19       ` Carlos O'Donell
  0 siblings, 1 reply; 31+ messages in thread
From: Szabolcs Nagy @ 2017-10-20 11:31 UTC (permalink / raw)
  To: Yubin Ruan; +Cc: nd, libc-help

On 20/10/17 12:23, Yubin Ruan wrote:
> Thanks Szabolcs,
> 
> 2017-10-20 18:32 GMT+08:00 Szabolcs Nagy <szabolcs.nagy@arm.com>:
>> On 18/10/17 15:18, Yubin Ruan wrote:
>>> Hi,
>>>
>>> I am writing to see if this is any util functions in libc that can
>>> help to determine it is currently running in a signal.
>>>
>>> I wrote some library and provide a function which will be used in many
>>> client code. However this function is not async-signal safe (it calls
>>> malloc(3)) so when it is called, I want to detect whether it is
>>> currently running in a signal handler. If it is, I can avoid calling
>>> those not-async-signal-safe functions which might cause deadlock.
>>>
>>
>> note that in posix as-safety is symmetric between the
>> interrupted code and interrupt handler: if any of the
>> interrupt and interrupt handler is as-safe then the
>> behaviour is well defined.
>>
>> so calling non-as-safe code in an asynchronous signal
>> handler is perfectly fine if the interrupted code is
>> as-safe.
>>
>> there are synchronous signals too, i.e. raise(sig),
>> and then the signal handler runs in well-defined state
>> (one can use signal masks to make sure a signal handler
>> only runs in such state)
> 
> Actually I think the point is that that piece of code should not run
> in a signal handler. That have nothing to do with sync-signal or
> async-signal code, because in both case we might encounter deadlock.
> From this perspective, that `in_signal_handler_context()' make sense
> to me.

there is no deadlock, malloc is safe to call in a signal
handler in posix if the signal interrupts as-safe code.

this entire mailing list thread assumes that only as-safe
code may run in a signal handler and that is wrong.

your api proposal does not make sense in a posix libc.
(which explains why it does not exists)

(the libc startup code may raise a reserved realtime
signal and make all programs run from a signal handler,
it would be a posix conform implementation and your
'in_signal_handler_context' would be always true)

>> so using "in_signal_handler_context()" is not a valid
>> way to verify the as-safety interface contract.
>>
>>> that is, I want a `in_signal_handler_context()' utility that can be
>>> used as this:
>>>
>>> int mylibfunc( void ) {
>>>     if( in_signal_handler_context() ) { return(-1) }
>>>     // rest of function goes here
>>>     return( 0 );
>>> }
>>>
>>>
>>> Yubin
>>>
>>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-20 11:31     ` Szabolcs Nagy
@ 2017-10-20 17:19       ` Carlos O'Donell
  2017-10-20 17:48         ` Szabolcs Nagy
  0 siblings, 1 reply; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-20 17:19 UTC (permalink / raw)
  To: Szabolcs Nagy, Yubin Ruan; +Cc: nd, libc-help

On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
> On 20/10/17 12:23, Yubin Ruan wrote:
>> Thanks Szabolcs,
>>
>> 2017-10-20 18:32 GMT+08:00 Szabolcs Nagy <szabolcs.nagy@arm.com>:
>>> On 18/10/17 15:18, Yubin Ruan wrote:
>>>> Hi,
>>>>
>>>> I am writing to see if this is any util functions in libc that can
>>>> help to determine it is currently running in a signal.
>>>>
>>>> I wrote some library and provide a function which will be used in many
>>>> client code. However this function is not async-signal safe (it calls
>>>> malloc(3)) so when it is called, I want to detect whether it is
>>>> currently running in a signal handler. If it is, I can avoid calling
>>>> those not-async-signal-safe functions which might cause deadlock.
>>>>
>>>
>>> note that in posix as-safety is symmetric between the
>>> interrupted code and interrupt handler: if any of the
>>> interrupt and interrupt handler is as-safe then the
>>> behaviour is well defined.
>>>
>>> so calling non-as-safe code in an asynchronous signal
>>> handler is perfectly fine if the interrupted code is
>>> as-safe.
>>>
>>> there are synchronous signals too, i.e. raise(sig),
>>> and then the signal handler runs in well-defined state
>>> (one can use signal masks to make sure a signal handler
>>> only runs in such state)
>>
>> Actually I think the point is that that piece of code should not run
>> in a signal handler. That have nothing to do with sync-signal or
>> async-signal code, because in both case we might encounter deadlock.
>> From this perspective, that `in_signal_handler_context()' make sense
>> to me.
> 
> there is no deadlock, malloc is safe to call in a signal
> handler in posix if the signal interrupts as-safe code.
> 
> this entire mailing list thread assumes that only as-safe
> code may run in a signal handler and that is wrong.

Correct.

I didn't want to go down more complex scenarios.

> your api proposal does not make sense in a posix libc.
> (which explains why it does not exists)
> 
> (the libc startup code may raise a reserved realtime
> signal and make all programs run from a signal handler,
> it would be a posix conform implementation and your
> 'in_signal_handler_context' would be always true)

Conservatively, if you see you are in a signal handler, 
and always run AS-safe code, you are always safe.

The converse is true too, if such an API call says you are
*not* in a signal handler, you may always run AS-unsafe
code because you know you could not have interrupted
AS-unsafe code.

The API could still have its uses?

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-20 17:19       ` Carlos O'Donell
@ 2017-10-20 17:48         ` Szabolcs Nagy
  2017-10-22  6:09           ` Carlos O'Donell
  0 siblings, 1 reply; 31+ messages in thread
From: Szabolcs Nagy @ 2017-10-20 17:48 UTC (permalink / raw)
  To: Carlos O'Donell, Yubin Ruan; +Cc: nd, libc-help

On 20/10/17 18:19, Carlos O'Donell wrote:
> On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
>> this entire mailing list thread assumes that only as-safe
>> code may run in a signal handler and that is wrong.
> 
> Correct.
> 
> I didn't want to go down more complex scenarios.
> 
>> your api proposal does not make sense in a posix libc.
>> (which explains why it does not exists)
>>
> 
> Conservatively, if you see you are in a signal handler, 
> and always run AS-safe code, you are always safe.
> 

yes, with as-safe code your are always safe.

> The converse is true too, if such an API call says you are
> *not* in a signal handler, you may always run AS-unsafe
> code because you know you could not have interrupted
> AS-unsafe code.
> 

that is usually true but may be false: if the
programmer thinks a call is as-safe when it isn't
that can cause problems even if the call is not in
a signal handler:

int main()
{
register_as_unsafe_handler();
call(); // ok if as-safe, not ok if as-unsafe
mask_signals();
}

> The API could still have its uses?
> 

yes it may have uses, but if a library tries to use
it for sanity checks, then the false positives will
cause headaches when somebody tries to use the
library correctly from a signal handler.

so it's a lot of complication for a not quite correct
check whether as-unsafe libc api is async reentered.

(e.g. a correct check would be inc/dec of a tls
counter in every as-unsafe libc api on entry/exit
and checking the counter, the libc could do this
without a public api change, may be possible to do
as an ld_preload hack if somebody really cares..
of course there are complications with callbacks
and, calls that go back to libc via plt etc, but
i think this can be made correct unlike the signal
context check)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-20 17:48         ` Szabolcs Nagy
@ 2017-10-22  6:09           ` Carlos O'Donell
  2017-10-22 23:39             ` where is the definition of idtype_t supposed to live? John Lumby
  2017-10-23 10:01             ` determine whether code is running in a signal handler context Szabolcs Nagy
  0 siblings, 2 replies; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-22  6:09 UTC (permalink / raw)
  To: Szabolcs Nagy, Yubin Ruan; +Cc: nd, libc-help

On 10/20/2017 10:48 AM, Szabolcs Nagy wrote:
> On 20/10/17 18:19, Carlos O'Donell wrote:
>> On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
>>> this entire mailing list thread assumes that only as-safe
>>> code may run in a signal handler and that is wrong.
>>
>> Correct.
>>
>> I didn't want to go down more complex scenarios.
>>
>>> your api proposal does not make sense in a posix libc.
>>> (which explains why it does not exists)
>>>
>>
>> Conservatively, if you see you are in a signal handler, 
>> and always run AS-safe code, you are always safe.
>>
> 
> yes, with as-safe code your are always safe.
> 
>> The converse is true too, if such an API call says you are
>> *not* in a signal handler, you may always run AS-unsafe
>> code because you know you could not have interrupted
>> AS-unsafe code.
>>
> 
> that is usually true but may be false: if the
> programmer thinks a call is as-safe when it isn't
> that can cause problems even if the call is not in
> a signal handler:
> 
> int main()
> {
> register_as_unsafe_handler();
> call(); // ok if as-safe, not ok if as-unsafe
> mask_signals();
> }

I don't understand this example.

Could you expand on this please?

>> The API could still have its uses?
>>
> 
> yes it may have uses, but if a library tries to use
> it for sanity checks, then the false positives will
> cause headaches when somebody tries to use the
> library correctly from a signal handler.

The false positive being that you run AS-safe code only,
but you *could* have run AS-unsafe if you'd accurately
tracked what kind of context you interrupted?

In that case I would not say or use the word "correct"
or "incorrect", since the code works, but it *might*
conservatively require you to run AS-safe only functions.
In that case it's a performance and algorithmic complexity
issue. It *is* correct because you never do anything that
is undefined according to the standard.

> so it's a lot of complication for a not quite correct
> check whether as-unsafe libc api is async reentered.

It is correct, but not precise.

> (e.g. a correct check would be inc/dec of a tls
> counter in every as-unsafe libc api on entry/exit
> and checking the counter, the libc could do this
> without a public api change, may be possible to do
> as an ld_preload hack if somebody really cares..
> of course there are complications with callbacks
> and, calls that go back to libc via plt etc, but
> i think this can be made correct unlike the signal
> context check)

s/correct/precise/g

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* where is the definition of idtype_t supposed to live?
  2017-10-22  6:09           ` Carlos O'Donell
@ 2017-10-22 23:39             ` John Lumby
  2017-10-23 13:57               ` Florian Weimer
  2017-10-23 10:01             ` determine whether code is running in a signal handler context Szabolcs Nagy
  1 sibling, 1 reply; 31+ messages in thread
From: John Lumby @ 2017-10-22 23:39 UTC (permalink / raw)
  To: libc-help

I recently built and installed glibc-2.24 myself and hit a problem while 
compiling an application which calls wait() :

/usr/include/x86_64-linux-gnu/sys/wait.h:148:20: error: unknown type 
name ‘idtype_t’
  extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop,
                     ^

After a bit of research I see that :

version      defined in
2.19            sys/wait.h           ##  where one might it expect it to 
live since  its only reference is in here
2.21            sys/waitflags.h   ##  strange home as it is an enum for 
an input parm,  not a WAITFLAG
2.24            ???                     ## after a make install into an 
install_root, I do not see it defined anywhere under the install_root

After adding the missing definition into the sys/wait.h for 2.24, all is 
well again.

I see it is present in the sources in glibc-2.24/posix/sys/wait.h but 
make somehow constructed some other one :
maybe related to this line
evaluate-test.sh conform/XOPEN2K8/sys/wait.h ...

It is more than likely I did something wrong,   but I have two questions:

1. building glibc-2.24 on a "normal" linux-x86-64 system with this in 
config.log
../glibc-2.24/configure 
--with-headers=/mnt/bluebild/linux-4.8.6-NETIF_SHIELD/usr/include 
--prefix=/usr --enable-add-ons=libidn --enable-kernel=4.8.6
  (building with gcc-5.4 if relevant,  shouldn't be)
where would you expect the definition for idtype_t to be in the 
installed system?

2. ditto for 2.26 if different   (I did not try this yet)

Cheers,   John

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-22  6:09           ` Carlos O'Donell
  2017-10-22 23:39             ` where is the definition of idtype_t supposed to live? John Lumby
@ 2017-10-23 10:01             ` Szabolcs Nagy
  2017-10-23 14:30               ` Carlos O'Donell
  1 sibling, 1 reply; 31+ messages in thread
From: Szabolcs Nagy @ 2017-10-23 10:01 UTC (permalink / raw)
  To: Carlos O'Donell, Yubin Ruan; +Cc: nd, libc-help

On 22/10/17 07:06, Carlos O'Donell wrote:
> On 10/20/2017 10:48 AM, Szabolcs Nagy wrote:
>> On 20/10/17 18:19, Carlos O'Donell wrote:
>>> On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
>>> The converse is true too, if such an API call says you are
>>> *not* in a signal handler, you may always run AS-unsafe
>>> code because you know you could not have interrupted
>>> AS-unsafe code.
>>>
>>
>> that is usually true but may be false: if the
>> programmer thinks a call is as-safe when it isn't
>> that can cause problems even if the call is not in
>> a signal handler:
>>
>> int main()
>> {
>> register_as_unsafe_handler();
>> call(); // ok if as-safe, not ok if as-unsafe
>> mask_signals();
>> }
> 
> I don't understand this example.
> 
> Could you expand on this please?

it means that as-unsafe code may interrupt the call.
(so if call is as-safe then there is no problem,
otherwise there is)

in practice this kind of design (where the signal handler
is as-unsafe and the main code is as-safe) is very rare,
but it is a valid design (e.g. think async-cancellation:
the main code is as-safe, and the interrupting code is
as-unsafe since it exits the thread running dtors etc).

>>> The API could still have its uses?
>>>
>>
>> yes it may have uses, but if a library tries to use
>> it for sanity checks, then the false positives will
>> cause headaches when somebody tries to use the
>> library correctly from a signal handler.
> 
> The false positive being that you run AS-safe code only,
> but you *could* have run AS-unsafe if you'd accurately
> tracked what kind of context you interrupted?
> 
> In that case I would not say or use the word "correct"
> or "incorrect", since the code works, but it *might*
> conservatively require you to run AS-safe only functions.
> In that case it's a performance and algorithmic complexity
> issue. It *is* correct because you never do anything that
> is undefined according to the standard.
> 

ok, with the assumption that the library call is only
required to be as-safe in signal handlers.

>> so it's a lot of complication for a not quite correct
>> check whether as-unsafe libc api is async reentered.
> 
> It is correct, but not precise.
> 
>> (e.g. a correct check would be inc/dec of a tls
>> counter in every as-unsafe libc api on entry/exit
>> and checking the counter, the libc could do this
>> without a public api change, may be possible to do
>> as an ld_preload hack if somebody really cares..
>> of course there are complications with callbacks
>> and, calls that go back to libc via plt etc, but
>> i think this can be made correct unlike the signal
>> context check)
> 
> s/correct/precise/g

ok.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: where is the definition of idtype_t supposed to live?
  2017-10-22 23:39             ` where is the definition of idtype_t supposed to live? John Lumby
@ 2017-10-23 13:57               ` Florian Weimer
       [not found]                 ` <BN6PR22MB16662DE3DFB590B3D6006F81A3460@BN6PR22MB1666.namprd22.prod.outlook.com>
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2017-10-23 13:57 UTC (permalink / raw)
  To: John Lumby; +Cc: libc-help

* John Lumby:

> I recently built and installed glibc-2.24 myself and hit a problem while 
> compiling an application which calls wait() :
>
> /usr/include/x86_64-linux-gnu/sys/wait.h:148:20: error: unknown type 
> name ‘idtype_t’
>   extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop,
>                      ^

You need to look at gcc -E output to see where the compiling is
picking up the definitions.  The glibc-provided header files are
consistent in this regard.

A possible explanation is that you installed new versions of the
header files into non-multi-arch paths, and GCC does not pick them up
because they are shadowed by older header files in multi-arch paths.

I'm not sure if Debian ever offered to contribute the multi-arch
header path changes upstream, but it's currently not possible to run
”make install” on an upstream tree and get a directory layout which is
compatible with Debian and downstreams.

Please avoid posting new questions to existing thread in the future.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: where is the definition of idtype_t supposed to live?
       [not found]                 ` <BN6PR22MB16662DE3DFB590B3D6006F81A3460@BN6PR22MB1666.namprd22.prod.outlook.com>
@ 2017-10-23 14:20                   ` Florian Weimer
  0 siblings, 0 replies; 31+ messages in thread
From: Florian Weimer @ 2017-10-23 14:20 UTC (permalink / raw)
  To: John Lumby; +Cc: libc-help

* John Lumby:

> Thanks Florian,
>
>
>    >  You need to look at gcc -E output to see where the compiling is
>    >  picking up the definitions.
>
>
> Yes I did that but my question was  I thought pure glibc,  distro-agnostic -
>
> after a make and make install into a install_root, where is the
> definition of idtype_t supposed to be?
>
> (in that install_root,  not in final distro layout)
>
> I don't think debian comes into it does it?  Unless you are indicating
> that make is influenced by distro choices?

I checked the 2.24 sources, and glibc assumes idtype_t is defined in
<sys/wait.h>.  “make install” assumes the path for that is
/usr/include/sys/wait.h, but that's not correct if the system uses
multi-arch paths.

>     > Please avoid posting new questions to existing thread in the future.
>
> Hmm, now I see from thread index that is what happened but why?  I
> thought changing the subj was enough.
> I did compose as reply to get the email address correct, did it
> somehow base on that?

Yes, changing the subject is not sufficient.  Apparently, you need to
start a new message from scratch in your mail client, and paste the
list address into that.

Please keep the thread on the mailing list.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-23 10:01             ` determine whether code is running in a signal handler context Szabolcs Nagy
@ 2017-10-23 14:30               ` Carlos O'Donell
  2017-10-24  1:00                 ` Yubin Ruan
  0 siblings, 1 reply; 31+ messages in thread
From: Carlos O'Donell @ 2017-10-23 14:30 UTC (permalink / raw)
  To: Szabolcs Nagy, Yubin Ruan; +Cc: nd, libc-help

On 10/23/2017 03:01 AM, Szabolcs Nagy wrote:
> On 22/10/17 07:06, Carlos O'Donell wrote:
>> On 10/20/2017 10:48 AM, Szabolcs Nagy wrote:
>>> On 20/10/17 18:19, Carlos O'Donell wrote:
>>>> On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
>>>> The converse is true too, if such an API call says you are
>>>> *not* in a signal handler, you may always run AS-unsafe
>>>> code because you know you could not have interrupted
>>>> AS-unsafe code.
>>>>
>>>
>>> that is usually true but may be false: if the
>>> programmer thinks a call is as-safe when it isn't
>>> that can cause problems even if the call is not in
>>> a signal handler:
>>>
>>> int main()
>>> {
>>> register_as_unsafe_handler();
>>> call(); // ok if as-safe, not ok if as-unsafe
>>> mask_signals();
>>> }
>>
>> I don't understand this example.
>>
>> Could you expand on this please?
> 
> it means that as-unsafe code may interrupt the call.
> (so if call is as-safe then there is no problem,
> otherwise there is)

Understood. Thank you for the clarification.

> in practice this kind of design (where the signal handler
> is as-unsafe and the main code is as-safe) is very rare,
> but it is a valid design (e.g. think async-cancellation:
> the main code is as-safe, and the interrupting code is
> as-unsafe since it exits the thread running dtors etc).

I agree completely. It is a valid design.

In this case, the proposed API would force considerable added
complexity.

>>>> The API could still have its uses?
>>>>
>>>
>>> yes it may have uses, but if a library tries to use
>>> it for sanity checks, then the false positives will
>>> cause headaches when somebody tries to use the
>>> library correctly from a signal handler.
>>
>> The false positive being that you run AS-safe code only,
>> but you *could* have run AS-unsafe if you'd accurately
>> tracked what kind of context you interrupted?
>>
>> In that case I would not say or use the word "correct"
>> or "incorrect", since the code works, but it *might*
>> conservatively require you to run AS-safe only functions.
>> In that case it's a performance and algorithmic complexity
>> issue. It *is* correct because you never do anything that
>> is undefined according to the standard.
>>
> 
> ok, with the assumption that the library call is only
> required to be as-safe in signal handlers.

Yes.

>>> so it's a lot of complication for a not quite correct
>>> check whether as-unsafe libc api is async reentered.
>>
>> It is correct, but not precise.
>>
>>> (e.g. a correct check would be inc/dec of a tls
>>> counter in every as-unsafe libc api on entry/exit
>>> and checking the counter, the libc could do this
>>> without a public api change, may be possible to do
>>> as an ld_preload hack if somebody really cares..
>>> of course there are complications with callbacks
>>> and, calls that go back to libc via plt etc, but
>>> i think this can be made correct unlike the signal
>>> context check)
>>
>> s/correct/precise/g
> 
> ok.

Please forgive my pedantism. I want everyone reading this
thread in the future to understand that correct in this case
is about avoiding undefined behaviour e.g. interrupting an
AS-unsafe context and running more AS-unsafe code. Rather than
a performance/complexity issue where an API uses a heuristic
that causes you to be AS-safe more often than you should.

The implementation of the API we are talking about could choose
to ignore the less frequently used case of AS-safe program being
interrupted by an AS-unsafe handler, in order to simplify the
code required to implement the API. Otherwise, as you state,
you need to precisely track the context being interrupted.

I think we've probably hashed out this issue to its maximum
extent :-) Hopefully the original poster has had their question
answered.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-23 14:30               ` Carlos O'Donell
@ 2017-10-24  1:00                 ` Yubin Ruan
  0 siblings, 0 replies; 31+ messages in thread
From: Yubin Ruan @ 2017-10-24  1:00 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Szabolcs Nagy, nd, libc-help

Thank you!

2017-10-23 22:30 GMT+08:00 Carlos O'Donell <carlos@redhat.com>:
> On 10/23/2017 03:01 AM, Szabolcs Nagy wrote:
>> On 22/10/17 07:06, Carlos O'Donell wrote:
>>> On 10/20/2017 10:48 AM, Szabolcs Nagy wrote:
>>>> On 20/10/17 18:19, Carlos O'Donell wrote:
>>>>> On 10/20/2017 04:31 AM, Szabolcs Nagy wrote:
>>>>> The converse is true too, if such an API call says you are
>>>>> *not* in a signal handler, you may always run AS-unsafe
>>>>> code because you know you could not have interrupted
>>>>> AS-unsafe code.
>>>>>
>>>>
>>>> that is usually true but may be false: if the
>>>> programmer thinks a call is as-safe when it isn't
>>>> that can cause problems even if the call is not in
>>>> a signal handler:
>>>>
>>>> int main()
>>>> {
>>>> register_as_unsafe_handler();
>>>> call(); // ok if as-safe, not ok if as-unsafe
>>>> mask_signals();
>>>> }
>>>
>>> I don't understand this example.
>>>
>>> Could you expand on this please?
>>
>> it means that as-unsafe code may interrupt the call.
>> (so if call is as-safe then there is no problem,
>> otherwise there is)
>
> Understood. Thank you for the clarification.
>
>> in practice this kind of design (where the signal handler
>> is as-unsafe and the main code is as-safe) is very rare,
>> but it is a valid design (e.g. think async-cancellation:
>> the main code is as-safe, and the interrupting code is
>> as-unsafe since it exits the thread running dtors etc).
>
> I agree completely. It is a valid design.
>
> In this case, the proposed API would force considerable added
> complexity.
>
>>>>> The API could still have its uses?
>>>>>
>>>>
>>>> yes it may have uses, but if a library tries to use
>>>> it for sanity checks, then the false positives will
>>>> cause headaches when somebody tries to use the
>>>> library correctly from a signal handler.
>>>
>>> The false positive being that you run AS-safe code only,
>>> but you *could* have run AS-unsafe if you'd accurately
>>> tracked what kind of context you interrupted?
>>>
>>> In that case I would not say or use the word "correct"
>>> or "incorrect", since the code works, but it *might*
>>> conservatively require you to run AS-safe only functions.
>>> In that case it's a performance and algorithmic complexity
>>> issue. It *is* correct because you never do anything that
>>> is undefined according to the standard.
>>>
>>
>> ok, with the assumption that the library call is only
>> required to be as-safe in signal handlers.
>
> Yes.
>
>>>> so it's a lot of complication for a not quite correct
>>>> check whether as-unsafe libc api is async reentered.
>>>
>>> It is correct, but not precise.
>>>
>>>> (e.g. a correct check would be inc/dec of a tls
>>>> counter in every as-unsafe libc api on entry/exit
>>>> and checking the counter, the libc could do this
>>>> without a public api change, may be possible to do
>>>> as an ld_preload hack if somebody really cares..
>>>> of course there are complications with callbacks
>>>> and, calls that go back to libc via plt etc, but
>>>> i think this can be made correct unlike the signal
>>>> context check)
>>>
>>> s/correct/precise/g
>>
>> ok.
>
> Please forgive my pedantism. I want everyone reading this
> thread in the future to understand that correct in this case
> is about avoiding undefined behaviour e.g. interrupting an
> AS-unsafe context and running more AS-unsafe code. Rather than
> a performance/complexity issue where an API uses a heuristic
> that causes you to be AS-safe more often than you should.
>
> The implementation of the API we are talking about could choose
> to ignore the less frequently used case of AS-safe program being
> interrupted by an AS-unsafe handler, in order to simplify the
> code required to implement the API. Otherwise, as you state,
> you need to precisely track the context being interrupted.
>
> I think we've probably hashed out this issue to its maximum
> extent :-) Hopefully the original poster has had their question
> answered.

Actually I understand all those things you discussed and I know that
choosing to ignore the less frequently used case of AS-safe program
being interrupted by an AS-unsafe will be a lot easier and bring less
overhead. However, I just want to make the library code generic...

I am still working on it and will let you know if there are any advance.

Thanks,
Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
                   ` (3 preceding siblings ...)
  2017-10-20 10:32 ` Szabolcs Nagy
@ 2017-11-27  8:43 ` Yubin Ruan
  2017-11-27 11:55   ` Florian Weimer
  4 siblings, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-11-27  8:43 UTC (permalink / raw)
  To: libc-help; +Cc: Carlos O'Donell, Will Hawkins, spc, noloader, Szabolcs Nagy

Hi friends,

Still remember this thread? It turn out that determining whether or not you
are currently in a signal handler is trivial with libunwind:

Assume that you have build libunwind properly:

------------------------------------
  #include <pthread.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <signal.h>
  #include <errno.h>
  #include <string.h>

  /* assume that you have build libunwind properly */
  #include "./libunwindout/include/libunwind.h"

  /* Simple error handling functions */
  #define handle_error_en(en, msg) \
          do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

  void show_backtrace(void) {
      unw_cursor_t cursor; unw_context_t uc;
      unw_word_t ip, sp;

      unw_getcontext(&uc);
      unw_init_local(&cursor, &uc);
      while(unw_step(&cursor) > 0) {
          unw_get_reg(&cursor, UNW_REG_IP, &ip);
          unw_get_reg(&cursor, UNW_REG_SP, &sp);

          /* Upon unwinding to a signal handler, you get a "1" */
          printf("Is in a signal handler [%d]\n",
                            unw_is_signal_frame(&cursor));

          printf("ip = %lx, sp = %lx \n", (long)ip, (long)sp);
      }
  }

  struct sigaction act;

  /* Upon receiving a SIGQUIT, this signal handler will be invoked */
  void sighandler(int signum, siginfo_t *info, void *ptr) {
      printf("Received signal: %d\n", signum);
      printf("signal originate from pid[%d]\n", info->si_pid);
      printf("Inside a signal handler...\n");
      show_backtrace();
      while(1)
          ;
      printf("[FATAL] quiting the signal handler\n");
  }

  int main(int argc, char *argv[]) {
  {
      printf("Pid of the current process: %d\n", getpid());

      memset(&act, 0, sizeof(act));

      act.sa_sigaction = sighandler;
      act.sa_flags = SA_SIGINFO;

      sigaction(SIGQUIT, &act, NULL);

      while(1)
         ;

      return 0;
  }
------------------ END -------------

So you should run this program, and then send it a SIGQUIT. Upon receiving a
SIGQUIT, the signal handler will be invoked and the show_backtrace() function
will be called, which will unwind the stack and eventually find the signal
handler frame, reporting 1.

More interesting, libunwind allows you to detect "remotely" with its
libunwind-ptrace module. By "remotely", it simply means that you can use
ptrace(2) to attach to a process and then you can use libunwind-ptrace to
detect the remote process is running in a signal handler.

For more info, please refer to libunwind's doc [1].

As of the mechanism which libunwind use, somebody refer to sigreturn(2) [2],
but I still investigate in that so more material will be pending.

Anyway, thank you for all your patience and discussion.

[1]: http://www.nongnu.org/libunwind/docs.html
[2]: https://stackoverflow.com/questions/47503630/detect-whether-tracee-is-in-a-signal-handler-when-using-ptrace/47503853

        Yubin

2017-10-18 22:18 GMT+08:00 Yubin Ruan <ablacktshirt@gmail.com>:
> Hi,
>
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
>
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.
>
> that is, I want a `in_signal_handler_context()' utility that can be
> used as this:
>
> int mylibfunc( void ) {
>     if( in_signal_handler_context() ) { return(-1) }
>     // rest of function goes here
>     return( 0 );
> }
>
>
> Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-11-27  8:43 ` Yubin Ruan
@ 2017-11-27 11:55   ` Florian Weimer
  2017-11-27 12:50     ` Yubin Ruan
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2017-11-27 11:55 UTC (permalink / raw)
  To: Yubin Ruan, libc-help
  Cc: Carlos O'Donell, Will Hawkins, spc, noloader, Szabolcs Nagy

On 11/27/2017 09:42 AM, Yubin Ruan wrote:
> Still remember this thread? It turn out that determining whether or not you
> are currently in a signal handler is trivial with libunwind:

This is incorrect.  libunwind (or any other unwinder) relies on 
information which is not always available.  And since you need to unwind 
the stack completely (if not executing in a signal handler), it is very 
slow.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-11-27 11:55   ` Florian Weimer
@ 2017-11-27 12:50     ` Yubin Ruan
  2017-11-27 12:51       ` Florian Weimer
  0 siblings, 1 reply; 31+ messages in thread
From: Yubin Ruan @ 2017-11-27 12:50 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-help, Carlos O'Donell, Will Hawkins, spc, noloader,
	Szabolcs Nagy

2017-11-27 19:55 GMT+08:00 Florian Weimer <fweimer@redhat.com>:
> On 11/27/2017 09:42 AM, Yubin Ruan wrote:
>>
>> Still remember this thread? It turn out that determining whether or not
>> you
>> are currently in a signal handler is trivial with libunwind:
>
>
> This is incorrect.  libunwind (or any other unwinder) relies on information
> which is not always available.

what information?

> And since you need to unwind the stack
> completely (if not executing in a signal handler), it is very slow.

slow speed is acceptable though.

Yubin

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-11-27 12:50     ` Yubin Ruan
@ 2017-11-27 12:51       ` Florian Weimer
  2017-11-27 12:58         ` Adhemerval Zanella
  0 siblings, 1 reply; 31+ messages in thread
From: Florian Weimer @ 2017-11-27 12:51 UTC (permalink / raw)
  To: Yubin Ruan
  Cc: libc-help, Carlos O'Donell, Will Hawkins, spc, noloader,
	Szabolcs Nagy

On 11/27/2017 01:50 PM, Yubin Ruan wrote:
> 2017-11-27 19:55 GMT+08:00 Florian Weimer <fweimer@redhat.com>:
>> On 11/27/2017 09:42 AM, Yubin Ruan wrote:
>>>
>>> Still remember this thread? It turn out that determining whether or not
>>> you
>>> are currently in a signal handler is trivial with libunwind:
>>
>>
>> This is incorrect.  libunwind (or any other unwinder) relies on information
>> which is not always available.
> 
> what information?

Unwind tables.  A correct stack pointer or frame pointer.

Florian

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: determine whether code is running in a signal handler context
  2017-11-27 12:51       ` Florian Weimer
@ 2017-11-27 12:58         ` Adhemerval Zanella
  0 siblings, 0 replies; 31+ messages in thread
From: Adhemerval Zanella @ 2017-11-27 12:58 UTC (permalink / raw)
  To: libc-help



On 27/11/2017 10:51, Florian Weimer wrote:
> On 11/27/2017 01:50 PM, Yubin Ruan wrote:
>> 2017-11-27 19:55 GMT+08:00 Florian Weimer <fweimer@redhat.com>:
>>> On 11/27/2017 09:42 AM, Yubin Ruan wrote:
>>>>
>>>> Still remember this thread? It turn out that determining whether or not
>>>> you
>>>> are currently in a signal handler is trivial with libunwind:
>>>
>>>
>>> This is incorrect.  libunwind (or any other unwinder) relies on information
>>> which is not always available.
>>
>> what information?
> 
> Unwind tables.  A correct stack pointer or frame pointer.
> 
> Florian

Just check libunwind usage and implementation for unw_is_signal_frame and
you will notice a lot of ad-hoc and heuristics which may or not fail
depending of the underlying system and binary. Also unw_is_signal_frame
is not implemented for all architectures or for all OS, it is hardly a
portable interface to rely on.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2017-11-27 12:58 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-18 14:18 determine whether code is running in a signal handler context Yubin Ruan
2017-10-18 18:34 ` Carlos O'Donell
2017-10-19  1:52   ` Yubin Ruan
2017-10-19  2:19     ` Carlos O'Donell
2017-10-19  2:39       ` Will Hawkins
2017-10-19  3:12         ` Carlos O'Donell
2017-10-19  4:07           ` Yubin Ruan
2017-10-19  4:56             ` Carlos O'Donell
2017-10-19  4:19           ` Will Hawkins
2017-10-19  4:01       ` Yubin Ruan
2017-10-19  2:59 ` Sean Conner
2017-10-19  3:12 ` Sean Conner
2017-10-19  3:51   ` Yubin Ruan
2017-10-19  7:10     ` Jeffrey Walton
2017-10-20 10:32 ` Szabolcs Nagy
2017-10-20 11:23   ` Yubin Ruan
2017-10-20 11:31     ` Szabolcs Nagy
2017-10-20 17:19       ` Carlos O'Donell
2017-10-20 17:48         ` Szabolcs Nagy
2017-10-22  6:09           ` Carlos O'Donell
2017-10-22 23:39             ` where is the definition of idtype_t supposed to live? John Lumby
2017-10-23 13:57               ` Florian Weimer
     [not found]                 ` <BN6PR22MB16662DE3DFB590B3D6006F81A3460@BN6PR22MB1666.namprd22.prod.outlook.com>
2017-10-23 14:20                   ` Florian Weimer
2017-10-23 10:01             ` determine whether code is running in a signal handler context Szabolcs Nagy
2017-10-23 14:30               ` Carlos O'Donell
2017-10-24  1:00                 ` Yubin Ruan
2017-11-27  8:43 ` Yubin Ruan
2017-11-27 11:55   ` Florian Weimer
2017-11-27 12:50     ` Yubin Ruan
2017-11-27 12:51       ` Florian Weimer
2017-11-27 12:58         ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).