You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Nick Kew <ni...@webthing.com> on 2004/07/20 01:54:02 UTC

setjmp/longjmp vs try/throw/catch

I have a couple of modules using third-party libraries that require me
to supply an "abort" function (or they'll abort by exiting).
For example, libjpeg in my mod_jpeg.

My preferred approach to this situation is usually to resort to C++,
put my code in a try/catch loop, and provide an abort handler that
throws an exception.  However, this doesn't play well with Apache,
and when I run it in gdb, the throw appears to generate an Abort.

Switching to setjmp/longjmp does appear to work well with apache and gcc.
But that leaves me wondering if I need to worry about thread-safety.
Is using setjmp/longjmp with Worker or Windoze MPM asking for trouble?
And if so, is there an alternative approach I could try?

-- 
Nick Kew

Re: Please Help

Posted by Manoj Kasichainula <ma...@io.com>.
On Tue, Jul 20, 2004 at 09:36:25PM -0400, Jeffrey K Pry wrote:
>I sent an email to that address and it failed. Can somebody please tell me
>what to do? Thank you all so much.

I just unsubbed the address manually. In the future, please save the 
message you got when subscribing to a list to know how to unsubscribe, 
or look in the headers for unsubscribe instructions.

Please Help

Posted by Jeffrey K Pry <JP...@verizon.net>.
I sent an email to that address and it failed. Can somebody please tell me
what to do? Thank you all so much.

Re: [patch] perchild.c (Re: setjmp/longjmp vs try/throw/catch)

Posted by Jeff Trawick <tr...@gmail.com>.
On Wed, 21 Jul 2004 05:33:18 +0900 (JST), Tsuyoshi SASAMOTO
<na...@super.win.ne.jp> wrote:
> And... in perchild.c, I found setjmp/longjmp is used unsafely
> (one jmpbuffer is shared by all threads).

patch looks reasonable on first glance; I'll look further with the
intention of committing soon-ish; bother me privately in a few days if
I forget ;)

(thanks!)

Re: [patch] perchild.c (Re: setjmp/longjmp vs try/throw/catch)

Posted by Rici Lake <ri...@speedy.com.pe>.
On 20-Jul-04, at 3:33 PM, Tsuyoshi SASAMOTO wrote:

> Please refer to this discussion about thread safety of setjmp/longjmp:
>      
> http://groups.google.com/groups? 
> threadm=9vg2ai$iie$1@engnews2.Eng.Sun.COM


The signal-to-noise ratio in that thread is very low :)

It is clear that setjmp/longjmp are *not* signal-safe; furthermore,  
signals interact badly with threads. It is certainly not ok to use  
longjmp in a signal handler, since there is no way of knowing which  
thread a signal handler might be running in. This does not make  
setjmp/longjmp thread unsafe (IMHO).

As Posix memorably states, using longjmp with a jump buffer from a  
different thread context is a "questionable practice ... not worthy of  
standardization".

R.


Re: Re^4: [patch] perchild.c

Posted by Jeff Trawick <tr...@gmail.com>.
On Tue, 3 Aug 2004 11:45:51 +0900 (JST), Tsuyoshi SASAMOTO
<na...@super.win.ne.jp> wrote:
> >attached patch looks a bit simpler; does it look okay to you?
> 
> Yes, it looks good and smart.
> 
> # I wonder about intention of the original code `if (!body)`;

if we received a message, it will have the '\0' in it (or there is a
bug in the send logic); so I'm not worried about the original check
for if (!body)...

> # in what case could it occur... recvmsg() could fail?

looks like pass_request() is what does the sendmsg(), yet there is an
error path in there -- when apr_brigade_flatten() fails; on this error
path, the connection to the recvmsg() loop would be dropped with no
sendmsg(), so recvmsg() would return a failure

> # If so, rather return value of the recvmsg() should be checked...

another thing I wonder about with regards to this AF_UNIX/SOCK_STREAM
logic: SOCK_STREAM isn't normally message oriented, but no logic on
the receive side to handle a partial read; when will that blow up?

I suspect (but haven't done the testingresearch) that the only thing
we can assume is sent over intact is the file escriptor that is
getting passed, and the receiver should be prepared to continue
reading after calling recvmsg()

--/--

also, why send over the request body on this initial "message"? how
would the request body get filtered?  seems like we should let the
process which is going to handle this request read the request body
through the input filter chain

Re^4: [patch] perchild.c

Posted by Tsuyoshi SASAMOTO <na...@super.win.ne.jp>.
>attached patch looks a bit simpler; does it look okay to you?

Yes, it looks good and smart.

# I wonder about intention of the original code `if (!body)`;
# in what case could it occur... recvmsg() could fail?
# If so, rather return value of the recvmsg() should be checked...


Tsuyoshi SASAMOTO
nazonazo@super.win.ne.jp

Re: Re^2: [patch] perchild.c

Posted by Jeff Trawick <tr...@gmail.com>.
On Mon, 2 Aug 2004 12:13:30 +0900 (JST), Tsuyoshi SASAMOTO
<na...@super.win.ne.jp> wrote:
> >(b) I omitted the unrelated fix which was part of your patch; care to
> >provide an explanation?
> 
> Sorry...
> ----------------------------------------------------------------------
>     body = strchr(iov.iov_base, 0); // `body` would be `headers + strlen(headers)`
>     if (!body) {
>         return 1;
>     }
> 
>     body++;                         // `body` would be `headers + strlen(headers) + 1`
>     bodylen = strlen(body);
> 
>     headers = iov.iov_base;
>     headerslen = body - headers;    // `body - headers` is `strlen(headers) + 1` !!!
> ----------------------------------------------------------------------
> So, `headerslen` should be `body - 1 - headers`.

attached patch looks a bit simpler; does it look okay to you?

Re^2: [patch] perchild.c

Posted by Tsuyoshi SASAMOTO <na...@super.win.ne.jp>.
>(b) I omitted the unrelated fix which was part of your patch; care to
>provide an explanation?

Sorry...
----------------------------------------------------------------------
    body = strchr(iov.iov_base, 0); // `body` would be `headers + strlen(headers)`
    if (!body) {
        return 1;
    }

    body++;                         // `body` would be `headers + strlen(headers) + 1`
    bodylen = strlen(body);

    headers = iov.iov_base;
    headerslen = body - headers;    // `body - headers` is `strlen(headers) + 1` !!!
----------------------------------------------------------------------
So, `headerslen` should be `body - 1 - headers`.


Tsuyoshi SASAMOTO
nazonazo@super.win.ne.jp

[patch] perchild.c (Re: setjmp/longjmp vs try/throw/catch)

Posted by Tsuyoshi SASAMOTO <na...@super.win.ne.jp>.
>Switching to setjmp/longjmp does appear to work well with apache and gcc.
>But that leaves me wondering if I need to worry about thread-safety.
>Is using setjmp/longjmp with Worker or Windoze MPM asking for trouble?
>And if so, is there an alternative approach I could try?

Please refer to this discussion about thread safety of setjmp/longjmp:
    http://groups.google.com/groups?threadm=9vg2ai$iie$1@engnews2.Eng.Sun.COM


And... in perchild.c, I found setjmp/longjmp is used unsafely
(one jmpbuffer is shared by all threads).


Tsuyoshi SASAMOTO
nazonazo@super.win.ne.jp

--- httpd-2.0/server/mpm/experimental/perchild/perchild.c	Tue Mar 16 08:08:41 2004
+++ httpd-2.0/server/mpm/experimental/perchild/perchild.c	Wed Jul 21 04:26:15 2004
@@ -137,7 +137,7 @@
 static int requests_this_child;
 static int num_listensocks = 0;
 static ap_pod_t *pod;
-static jmp_buf jmpbuffer;
+static jmp_buf *jmpbuffers;
 
 struct child_info_t {
     uid_t uid;
@@ -617,7 +617,7 @@
     bodylen = strlen(body);
 
     headers = iov.iov_base;
-    headerslen = body - headers;
+    headerslen = body - 1 - headers;
 
     bucket = apr_bucket_heap_create(body, bodylen, NULL, alloc);
     APR_BRIGADE_INSERT_HEAD(bb, bucket);
@@ -758,7 +758,7 @@
                 }
             }
             apr_thread_mutex_unlock(idle_thread_count_mutex);
-            if (setjmp(jmpbuffer) != 1) {
+            if (setjmp(jmpbuffers[thread_num]) != 1) {
                 process_socket(ptrans, csd, conn_id, bucket_alloc);
             }
             else {
@@ -1668,6 +1668,8 @@
     }
     ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable));
 
+    jmpbuffers = (jmp_buf *)apr_palloc(p, thread_limit * sizeof(jmp_buf));
+
     return OK;
 }
 
@@ -1704,7 +1706,7 @@
                              ap_server_conf, "Could not pass request to proper "
                              "child, request will not be honored.");
             }
-            longjmp(jmpbuffer, 1); 
+            longjmp(jmpbuffers[thread_num], 1); 
         }
         return OK;
     }

Re: setjmp/longjmp vs try/throw/catch

Posted by Nick Kew <ni...@webthing.com>.
On Tue, 20 Jul 2004, William A. Rowe, Jr. wrote:

> IIRC - all setjmp and other usually-thread-agnostic calls in a normal clib
> were redesigned to use TLS in the Win32 msvcrt lib, long before most
> Unixes considered implementing threads :)  I believe on win32 you will
> be fine, I'd be more worried about the thread implementations.

I have it on credible authority (in IRC from someone I believe, after
I asked) that POSIX requires it to be thread-safe.  That's good enough
for me: tells me I don't need to advise the Client to use prefork.

> This sure sounds like an abstraction we should assist with using apr.

Agreed.  But I don't have APR karma to introduce the idea there.

-- 
Nick Kew

Re: setjmp/longjmp vs try/throw/catch

Posted by Nick Kew <ni...@webthing.com>.
On Tue, 20 Jul 2004, William A. Rowe, Jr. wrote:

> IIRC - all setjmp and other usually-thread-agnostic calls in a normal clib
> were redesigned to use TLS in the Win32 msvcrt lib, long before most
> Unixes considered implementing threads :)  I believe on win32 you will
> be fine, I'd be more worried about the thread implementations.

I have it on credible authority (in IRC from someone I believe, after
I asked) that POSIX requires it to be thread-safe.  That's good enough
for me: tells me I don't need to advise the Client to use prefork.

> This sure sounds like an abstraction we should assist with using apr.

Agreed.  But I don't have APR karma to introduce the idea there.

-- 
Nick Kew

Re: setjmp/longjmp vs try/throw/catch

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 06:54 PM 7/19/2004, Nick Kew wrote:

>I have a couple of modules using third-party libraries that require me
>to supply an "abort" function (or they'll abort by exiting).
>For example, libjpeg in my mod_jpeg.
>
>My preferred approach to this situation is usually to resort to C++,
>put my code in a try/catch loop, and provide an abort handler that
>throws an exception.  However, this doesn't play well with Apache,
>and when I run it in gdb, the throw appears to generate an Abort.
>
>Switching to setjmp/longjmp does appear to work well with apache and gcc.
>But that leaves me wondering if I need to worry about thread-safety.
>Is using setjmp/longjmp with Worker or Windoze MPM asking for trouble?
>And if so, is there an alternative approach I could try?

IIRC - all setjmp and other usually-thread-agnostic calls in a normal clib
were redesigned to use TLS in the Win32 msvcrt lib, long before most
Unixes considered implementing threads :)  I believe on win32 you will
be fine, I'd be more worried about the thread implementations.

This sure sounds like an abstraction we should assist with using apr.

Bill 


Re: setjmp/longjmp vs try/throw/catch

Posted by "William A. Rowe, Jr." <wr...@rowe-clan.net>.
At 06:54 PM 7/19/2004, Nick Kew wrote:

>I have a couple of modules using third-party libraries that require me
>to supply an "abort" function (or they'll abort by exiting).
>For example, libjpeg in my mod_jpeg.
>
>My preferred approach to this situation is usually to resort to C++,
>put my code in a try/catch loop, and provide an abort handler that
>throws an exception.  However, this doesn't play well with Apache,
>and when I run it in gdb, the throw appears to generate an Abort.
>
>Switching to setjmp/longjmp does appear to work well with apache and gcc.
>But that leaves me wondering if I need to worry about thread-safety.
>Is using setjmp/longjmp with Worker or Windoze MPM asking for trouble?
>And if so, is there an alternative approach I could try?

IIRC - all setjmp and other usually-thread-agnostic calls in a normal clib
were redesigned to use TLS in the Win32 msvcrt lib, long before most
Unixes considered implementing threads :)  I believe on win32 you will
be fine, I'd be more worried about the thread implementations.

This sure sounds like an abstraction we should assist with using apr.

Bill