public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* __attribute__((cleanup(function)) versus try/finally
@ 2003-05-06 19:56 Jason Merrill
  2003-05-08 11:59 ` Gabriel Dos Reis
  2003-05-08 18:30 ` Mike Stump
  0 siblings, 2 replies; 52+ messages in thread
From: Jason Merrill @ 2003-05-06 19:56 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 162 bytes --]

This discussion started on the steering committee list, but we agreed that
it didn't belong there, so I'm forwarding my and Mark's mail to start the
discussion.


[-- Attachment #2.1: Type: text/plain, Size: 286 bytes --]

Subject: Topics
Content-length: 249

Topics:
   Re: __attribute__((cleanup(function)) versus try/finally
   Re: __attribute__((cleanup(function)) versus try/finally
   Re: __attribute__((cleanup(function)) versus try/finally
   Re: __attribute__((cleanup(function)) versus try/finally


[-- Attachment #2.2: Type: text/plain, Size: 3705 bytes --]

Date: Tue, 06 May 2003 12:50:25 -0400
From: Jason Merrill <jason@redhat.com>
Subject: Re: __attribute__((cleanup(function)) versus try/finally
Message-ID: <wvlwuh4aujy.fsf@prospero.boston.redhat.com>
References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>
MIME-Version: 1.0
Content-length: 3393

On Tue, 6 May 2003 15:20:59 +0200 (CEST), Gerald Pfeifer wrote:

> For those that didn't follow gcc-patches, there has been strong
> disagreement on how to implement exception handling in C for some
> time now:
>
>  o RTH (and others) are strongly in favor of try/finally, which is
>  implemented by several others compilers.

Myself among them.  try/finally is well defined, and already implemented in
other languages and other C compilers.  IMO the explicit syntax is in
keeping with the spirit of C.  If we have any exception handling support
whatsoever in C, it should be try/finally.  And we've (for some definition
of we) always intended to have some EH in C someday.  Now that we're trying
to integrate pthreads with EH, it's time.

>  o Mark (and others) are against adding try/finally and favor adding
>  a different extension: __attribute__((cleanup(function)) which is
>  "lighter" in a sense.

I agree with Alex's comments on this approach; it's trying to introduce the
C++ object model into C, which seems like rather a backwards way to
approach exception cleanliness.

FWIW, here's a post to the glibc list from someone who worked on threading
in Tru64, the closest thing to a prior implementation.

  http://sources.redhat.com/ml/libc-alpha/1999-08/msg00038.html

Here's the beginning of the try/finally thread:

  http://gcc.gnu.org/ml/gcc-patches/2002-11/threads.html#00239

Which includes the message Michael mentions:

  http://gcc.gnu.org/ml/gcc-patches/2002-11/msg00451.html

To sum up, the objections to try/finally amounted to:

1) -fexceptions overhead

  On any modern OS, the overhead is only on disk unless EH constructs are
  actually used.  The unwind tables are only loaded if an exception is
  thrown.  By contrast, registering pthread cleanups to work with the
  longjmp_unwind solution involves a setjmp, which needs to run whether or
  not you throw an exception.

2) implementing something before standardization

  That's why the patch doesn't create "try" and "finally" keywords, but
  rather "__try" and "__finally".  Though I can't imagine any similar
  construct having different semantics.

3) poorly defined semantics

  Nonsense.  As I wrote early in the thread:

  The code in the finally block is run on exit from the try block, except
  that exiting a try block with a corresponding finally block via longjmp
  or computed goto has undefined behavior.

  It's simple, it's straightforward, it shares implementation with the Java
  frontend.  There's tons of prior art.

4) it's the wrong choice

  Other proposed solutions were:
    adding destructors to C (i.e. attribute cleanup),
      Again, I don't want to get into object lifetime stuff in C.
    try/catch instead
      C++ doesn't have try/finally because it has destructors.  C doesn't
      need catch for pthreads, but we could implement it later if we want
      full EH in C.
    specialized pthread primitive builtins
      ...which would be modelled internally with TRY_FINALLY_EXPR.  I could
      accept this, but I'd rather provide the more general facility and let
      the pthreads library worry about pthreads semantics.
    longjmp_unwind
      ...which has now been implemented, though I don't think the pthread
      library uses it yet.

  IMO none of these are nearly as clean in design as try/finally.  Any one
  of them will be more of a maintenance headache.

Jason


[-- Attachment #2.3: Type: text/plain, Size: 2160 bytes --]

Date: 06 May 2003 11:29:01 -0700
From: Mark Mitchell <mark@codesourcery.com>
Subject: Re: __attribute__((cleanup(function)) versus try/finally
Message-Id: <1052245742.2583.315.camel@doubledemon.codesourcery.com>
References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>
MIME-Version: 1.0
Content-length: 1836

On Tue, 2003-05-06 at 06:20, Gerald Pfeifer wrote:
> Michael Matz asked that the SC addresses this issue, and I'm forwarding
> his message below.  I have also suggested to provide more detailed
> technical arguments which I'll forward as well.
> 
> For those that didn't follow gcc-patches, there has been strong
> disagreement on how to implement exception handling in C for some
> time now:
> 
>  o RTH (and others) are strongly in favor of try/finally, which is
>  implemented by several others compilers.
> 
>  o Mark (and others) are against adding try/finally and favor adding
>  a different extension: __attribute__((cleanup(function)) which is
>  "lighter" in a sense.

I think RTH accepts the attribute solution as well.  He would prefer
try/finally, as I would prefer no extension, but I think we are both
willing to accept the attribute.

A key point (which seems to be missed by most people in this dicussion)
is that you do not need a language extension to get the correct
behavior.  

You simply need to have the exception-handling mechanism aware of the C
cleanup stack.

In fact, that solution delivers maximum performance:

(1) C functions do not need to have handler code inserted.

(2) You do not have to transfer control from the EH mechanism to the
stack frame of the caller in order to perform the cleanups.

The __attribute__ solution can be implemented with the same optimal
performance, but that does not seem to be the way in which people intend
to implement it.

The try/finally solution cannot be implemented with this same
performance; it will, in fact, exact a performance price, in terms of
both code space and the speed at which cleanups are run, on all
systems.  On systems with setjmp/longjmp exceptions, both costs will be
very high indeed.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com


[-- Attachment #2.4: Type: text/plain, Size: 2498 bytes --]

Date: Tue, 06 May 2003 15:15:48 -0400
From: Jason Merrill <jason@redhat.com>
To: Mark Mitchell <mark@codesourcery.com>
Subject: Re: __attribute__((cleanup(function)) versus try/finally
Message-ID: <wvlissnc2e3.fsf@prospero.boston.redhat.com>
References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>
	<1052245742.2583.315.camel@doubledemon.codesourcery.com>
MIME-Version: 1.0
Content-length: 2086

On 06 May 2003 11:29:01 -0700, Mark Mitchell <mark@codesourcery.com> wrote:

> A key point (which seems to be missed by most people in this dicussion)
> is that you do not need a language extension to get the correct behavior.
>
> You simply need to have the exception-handling mechanism aware of the C
> cleanup stack.

That would be an extension too, wouldn't it?

In any case, how are you thinking to do this?  You've mentioned such a
thing before, but I haven't noticed an implementation sketch.

> In fact, that solution delivers maximum performance:
>
> (1) C functions do not need to have handler code inserted.
>
> (2) You do not have to transfer control from the EH mechanism to the
> stack frame of the caller in order to perform the cleanups.
>
> The __attribute__ solution can be implemented with the same optimal
> performance, but that does not seem to be the way in which people intend
> to implement it.

> The try/finally solution cannot be implemented with this same
> performance; it will, in fact, exact a performance price, in terms of
> both code space and the speed at which cleanups are run, on all
> systems.  On systems with setjmp/longjmp exceptions, both costs will be
> very high indeed.

Hmm.  Are you talking about representing cleanups in the LSDA via a
function pointer and a CFA offset for the argument object?  That way you
still need unwind info and PC range tables, but you don't put any code into
the function itself.

This strategy was discussed at the ABI meetings; I think Intel was
advocating it.  We all agreed that it was a valid approach, but most of us
thought that having the cleanups inline offered more optimization
opportunities (code motion into the landing pad, jumping between cleanups,
inlining destructors, not forcing the object into the stack).

It might make sense to do this for C functions, though.

It's somewhat more complicated to do this sort of thing with try/finally,
since it allows an arbitrary block of code, not just a call, but the
GOTO_SUBROUTINE_EXPR expansion of TRY_FINALLY_EXPR is a very similar idea.

Jason


[-- Attachment #2.5: Type: text/plain, Size: 3013 bytes --]

Date: 06 May 2003 12:38:09 -0700
From: Mark Mitchell <mark@codesourcery.com>
To: Jason Merrill <jason@redhat.com>
Subject: Re: __attribute__((cleanup(function)) versus try/finally
Message-Id: <1052249890.31850.338.camel@doubledemon.codesourcery.com>
References: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>
	<1052245742.2583.315.camel@doubledemon.codesourcery.com> 
	<wvlissnc2e3.fsf@prospero.boston.redhat.com>
MIME-Version: 1.0
Content-length: 2546

> > You simply need to have the exception-handling mechanism aware of the C
> > cleanup stack.
> 
> That would be an extension too, wouldn't it?

Yes -- but on the library side, not on the compiler side.  The library's
going to have extensions no matter what -- this whole pthread
cancellation strategy is an extension.
 
> In any case, how are you thinking to do this?  You've mentioned such a
> thing before, but I haven't noticed an implementation sketch.

I did on the gcc list, but it got lost in the noise, I think.  

The strategy is:

(1) Have pthread_cleanup_push include the current $sp in the cleanup
record.  Otherwise, use the same data structures currently used by
glibc's pthread_cleanup_push.

(2) When an exception is thrown:

- Figure out where the next handler/cleanup will be.

  (By hypothesis, this is not going to be in C code, because we don't
  have try/finally in C.)

- If unwinding the stack to that destination will result in $sp be older
than the $sp recorded in the cleanup at the top of the C cleanup stack,
run C cleanups until that is no longer true.

- Transfer control to the handler as is done now.

> > The try/finally solution cannot be implemented with this same
> > performance; it will, in fact, exact a performance price, in terms of
> > both code space and the speed at which cleanups are run, on all
> > systems.  On systems with setjmp/longjmp exceptions, both costs will be
> > very high indeed.
> 
> Hmm.  Are you talking about representing cleanups in the LSDA via a
> function pointer and a CFA offset for the argument object?  That way you
> still need unwind info and PC range tables, but you don't put any code into
> the function itself.

I'm not as sophisticated as you about this; I don't actually know what
all the EH implementation details are.  With the scheme above, you do
still need PC range tables and (some?) unwind information, but you don't
put any code into the function.  I keep mumbling that I think you might
be able to avoid some of the unwind information for C, but I've never
done what it would take to prove or disprove that assertion.  

The key point is that you don't need any handler code in the function.

The observation behind this is that pthread cleanups -- unlike C++ catch
clauses -- do not need to execute in the frame of the function that
pushed them.  They just need to execute while the stack is still there,
in case the "arg" to the function directly or indirectly references
stuff on the stack.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com


^ permalink raw reply	[flat|nested] 52+ messages in thread
[parent not found: <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>]
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-07 10:18 Ranjit Mathew
  2003-05-07 13:54 ` Jason Merrill
                   ` (2 more replies)
  0 siblings, 3 replies; 52+ messages in thread
From: Ranjit Mathew @ 2003-05-07 10:18 UTC (permalink / raw)
  To: jason; +Cc: gcc

 > 2) implementing something before standardization
 >
 >   That's why the patch doesn't create "try" and "finally" keywords, but
 >   rather "__try" and "__finally".  Though I can't imagine any similar
 >   construct having different semantics.

Sorry to butt in into this discussion, but I would
like to point out that it would be a BAD idea to name
these "__try/__finally" simply because these are used
in the Windows world to deal with Windows Structured
Exception Handling (SEH) and are a language extension
introduced by MS Visual C/C++ (and adopted by other
commercial compilers for Windows):

http://msdn.microsoft.com/library/en-us/vccelng/htm/statem_31.asp

There are quite a few commercial and non-commercial
programs out there that use these keywords.

However unfortunate you consider this situation to be,
if GCC introduces these keywords, it is going to create
a lot of confusion.

The same issue was pointed out (albeit in passing)
when Aldy Hernandez had submitted his __try/__finally
patch to GCC for C.

Now I have an issue somewhat related to this
discussion that I hope someone would be able to
shed some light on: on Windows, the Cygwin/MinGW
targets have had to give up on DW2 EH in favour of
SJLJ purely because exceptions could not be
thrown from a callback function, across the
Windows Event Dispatcher stack to the handler
of the exception.

Such code is common in Windows GUI applications
created with GCC (MinGW).

The "core" message loop of such Windows GUI programs
is roughly like the following:

   while( GetMessage( &msg, NULL, 0, 0)) {
     try {
       TranslateMessage( &msg);
       DispatchMessage( &msg);
     } catch (...) {
       /* Whatever */
     }
   }

DispatchMessage( ) is a Win32 API that ultimately
delivers the message to a registered "window procedure"
callback function within the application that
handles this message and might possibly throw an
exception.

Since the Win32 API stack does not have DW2 EH
unwind information, the program just terminates
when an exception is thrown (if using DW2 EH).

SJLJ does not have any such problems.

In fact, this seems to be a fundamental limitation
of the DW2 EH mechanism and not just on Windows.

So is there a way out of this?

MD_FALLBACK_FRAME_STATE_FOR looks a bit promising
but how do we generalise it to any "foreign"
caller?

Many thanks in advance for answering these.

Ranjit.

-- 
Ranjit Mathew          Email: rmathew AT hotmail DOT com

Bangalore, INDIA.      Web: http://ranjitmathew.tripod.com/

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-08  7:49 Ranjit Mathew
  2003-05-08 21:21 ` Richard Henderson
  0 siblings, 1 reply; 52+ messages in thread
From: Ranjit Mathew @ 2003-05-08  7:49 UTC (permalink / raw)
  To: gcc

> > The same issue was pointed out (albeit in passing)
> > when Aldy Hernandez had submitted his __try/__finally
> > patch to GCC for C.
>
>And I responded at the time claiming that the semantics of
>the two extensions are identical.

Very similar, but not identical, AFAICT:

    http://msdn.microsoft.com/library/en-us/vccelng/htm/state_14.asp

The __finally block is executed in case of both "normal" C++ exceptions
as well as "faults" such as accessing a NULL pointer, dividing by zero,
etc.

Of course this would tie in with integrating SEH support into GCC,
a brave attempt at which can be found at:

    http://reactos.wox.org/index.php?page=gccseh

in which case my point becomes moot.


> > Since the Win32 API stack does not have DW2 EH
> > unwind information, the program just terminates
> > when an exception is thrown (if using DW2 EH).
> >
> > SJLJ does not have any such problems.
> >
> > In fact, this seems to be a fundamental limitation
> > of the DW2 EH mechanism and not just on Windows.
>
>Yes.  Such is the price you pay for not saving all of the
>registers up front when an exception is *not* thrown.

IIRC, till some time ago "-fsjlj-exceptions" used to be available
that should allow such fringe cases to work albeit with a
performance hit.

Otherwise DW2 EH is *way better* than SJLJ as you all
know very well and should be the default.

Does anyone know why "fsjlj-exceptions" support was
dropped and made a configure time option?


> > MD_FALLBACK_FRAME_STATE_FOR looks a bit promising
> > but how do we generalise it to any "foreign" caller?
>
>Eh, MD_FALLBACK_FRAME_STATE_FOR isn't really generalizable.
>You could perhaps hack it to parse SEH unwind data, but...

SEH is an SJLJ type scheme:

http://www.microsoft.com/msj/0197/Exception/Exception.aspx


>Another possibility is to give up on unwind-dw2.c entirely
>and write a new unwinder that uses the SEH bits in the Win32
>API directly, all the time.  Then (1) you'd be able to unwind
>through Windows routines and (2) there'd be no "confusion"
>about the supposed "differences" in try/finally.

Possible, but it feels awful to throw away the fantastic DW2 EH...

:-(

Ranjit.

_________________________________________________________________
Dreaming of a holiday? Make it happen.  
http://server1.msn.co.in/sp03/switzerlandtourism/index.asp In Switzerland!

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-09  9:23 Ranjit Mathew
  2003-05-09  9:31 ` Andrew Haley
  0 siblings, 1 reply; 52+ messages in thread
From: Ranjit Mathew @ 2003-05-09  9:23 UTC (permalink / raw)
  To: rth; +Cc: gcc

> > The __finally block is executed in case of both "normal" C++ exceptions
> > as well as "faults" such as accessing a NULL pointer, dividing by zero,
> > etc.
>
>And your point is... ?  Libjava does this for dwarf2 EH on Linux.

Yes, I know (http://gcc.gnu.org/java/port-signals.html).

The Windows port of GCJ also has a similar hack using SEH Win32 APIs. 
However,
unlike signal handlers on Linux, Windows actually expects the
"UnexpectedExceptionHandler" routine to *return* with a value to it - since
the current implementation doesn't, a simple thing like two Java
NullPointerExceptions results in a hung process on Win2K!

So if we manage to make it work reliably, we can then claim identical
semantics indeed. Touche.


>Incidentally, I would be willing to review and incorporate pieces
>of this into gcc.
>
>I can't promise anything about "__except" or "__leave" (indeed, I
>suspect that they _won't_ be incorporated), but we can at least talk
>about including SEH for general exception handling.  At minimum you'd
>be able to use catch(...) instead of "__except" in C++.

This is good news for all MinGW users, thank you! Casper Hornstrup
(chorns at users dot sourceforge dot net) of the ReactOS team, who
has created the SEH enabled GCC mentioned earlier, would be delighted
to hear this I think.

Ranjit.

_________________________________________________________________
Dreaming of a holiday? Make it happen.  
http://server1.msn.co.in/sp03/switzerlandtourism/index.asp In Switzerland!

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-09  9:54 Ranjit Mathew
  2003-05-09 10:16 ` Andrew Haley
  0 siblings, 1 reply; 52+ messages in thread
From: Ranjit Mathew @ 2003-05-09  9:54 UTC (permalink / raw)
  To: aph; +Cc: gcc

>  > > > The __finally block is executed in case of both "normal" C++ 
>exceptions
>  > > > as well as "faults" such as accessing a NULL pointer, dividing by 
>zero,
>  > > > etc.
>  > >
>  > >And your point is... ?  Libjava does this for dwarf2 EH on Linux.
>  >
>  > Yes, I know (http://gcc.gnu.org/java/port-signals.html).
>
>Oh no, that page is way, way out of date.  I must rewrite it.
>There's not even any mention of MD_FALLBACK_FRAME_STATE_FOR, which is
>the crucial part of the job.

Maybe laymen aren't supposed to be implementing MAKE_THROW_FRAME for
libgcj ;-), but I think it should at least be pointed out that the crucial 
reasons
the given example works *at all* are that:

1. Linux does not care if the signal handler returns or not (unlike 
Windows).

2. A proper MD_FALLBACK_FRAME_STATE_FOR definition for Linux/x86 ensures
   that unwinding works through the intervening signal handler frame when a
   "throw" occurs, instead of aborting the process with an uncerimonious
   "abnormal program termination" as would have happened otherwise.

Ranjit.

_________________________________________________________________
Want to get married? Try online matrimony. 
http://server1.msn.co.in/features/onlinematrimony/index.asp It's cool.

^ permalink raw reply	[flat|nested] 52+ messages in thread
* Re: __attribute__((cleanup(function)) versus try/finally
@ 2003-05-13 21:33 Richard Kenner
  2003-05-13 22:11 ` Richard Henderson
  0 siblings, 1 reply; 52+ messages in thread
From: Richard Kenner @ 2003-05-13 21:33 UTC (permalink / raw)
  To: rth; +Cc: gcc

    > In any case, there are some semantics to be defined; if a cleanup throws
    > an exception, what happens?

    At present, the old exception doesn't get destroyed, and the new
    exception propagates.  I'm not really sure *what* should be said
    except that it's undefined behaviour.

Just FYI, in Ada this is defined and the action depends on how the
cleanup was invoked.

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

end of thread, other threads:[~2003-05-15 17:23 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-06 19:56 __attribute__((cleanup(function)) versus try/finally Jason Merrill
2003-05-08 11:59 ` Gabriel Dos Reis
2003-05-08 15:02   ` Jason Merrill
2003-05-08 18:30 ` Mike Stump
2003-05-08 20:49   ` Richard Henderson
2003-05-08 22:29     ` Mike Stump
2003-05-13  0:07       ` Geoff Keating
2003-05-13 21:27         ` Richard Henderson
2003-05-14  1:14           ` Geoff Keating
2003-05-14  7:41             ` Richard Henderson
2003-05-14 21:11               ` Geoff Keating
2003-05-14 22:20                 ` Richard Henderson
     [not found] <Pine.BSF.4.55.0305061457450.57349@acrux.dbai.tuwien.ac.at>
     [not found] ` <1052245742.2583.315.camel@doubledemon.codesourcery.com>
     [not found]   ` <wvlissnc2e3.fsf@prospero.boston.redhat.com>
     [not found]     ` <1052249890.31850.338.camel@doubledemon.codesourcery.com>
2003-05-06 21:04       ` Jason Merrill
2003-05-06 21:24         ` Mark Mitchell
2003-05-07 21:21           ` Jason Merrill
2003-05-07 22:18             ` Mark Mitchell
2003-05-07 23:01               ` Jason Merrill
2003-05-08 12:05               ` Gabriel Dos Reis
2003-05-09  5:46               ` Kai Henningsen
2003-05-06 21:52         ` Anthony Green
2003-05-08 17:44         ` Mike Stump
2003-05-08 17:45           ` Jason Merrill
2003-05-08 18:40             ` Mark Mitchell
2003-05-08 19:06               ` Alexandre Oliva
2003-05-08 19:47                 ` Mark Mitchell
2003-05-08 20:19                   ` Alexandre Oliva
2003-05-08 21:18                   ` Jason Merrill
2003-05-13 21:10                     ` Mark Mitchell
2003-05-13 21:25                       ` Richard Henderson
2003-05-13 21:41                         ` Mark Mitchell
2003-05-13 22:16                           ` Richard Henderson
2003-05-13 21:31                       ` Gabriel Dos Reis
2003-05-15 17:00                       ` Jason Merrill
2003-05-15 17:23                         ` Mark Mitchell
2003-05-09 19:41                   ` Kai Henningsen
2003-05-08 19:37               ` Jason Merrill
2003-05-07  0:14   ` Richard Henderson
2003-05-07  2:32     ` Mark Mitchell
2003-05-07 10:18 Ranjit Mathew
2003-05-07 13:54 ` Jason Merrill
2003-05-07 18:23 ` Richard Henderson
2003-05-08 18:02 ` Mike Stump
2003-05-08  7:49 Ranjit Mathew
2003-05-08 21:21 ` Richard Henderson
2003-05-09  9:23 Ranjit Mathew
2003-05-09  9:31 ` Andrew Haley
2003-05-09  9:54 Ranjit Mathew
2003-05-09 10:16 ` Andrew Haley
2003-05-09 12:08   ` Fergus Henderson
2003-05-09 12:49   ` Jamie Lokier
2003-05-13 21:33 Richard Kenner
2003-05-13 22:11 ` Richard Henderson

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).