From patchwork Tue Oct 20 20:24:12 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 9281 Received: (qmail 74475 invoked by alias); 20 Oct 2015 20:24:25 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 74440 invoked by uid 89); 20 Oct 2015 20:24:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=no version=3.3.2 X-HELO: sonata.ens-lyon.org Date: Tue, 20 Oct 2015 22:24:12 +0200 From: Samuel Thibault To: libc-alpha@sourceware.org, roland@hack.frob.com, bug-hurd@gnu.org Subject: hurd: Fix longjmp from signal handler Message-ID: <20151020202412.GC2752@var.home> Mail-Followup-To: libc-alpha@sourceware.org, roland@hack.frob.com, bug-hurd@gnu.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30) Hello, The patch below fixes a corner case of signals: when longjumping from a signal handler, the code currently restores the reply port used by the main code. But since we possibly longjmp over a pending RPC, we should rather just kill that reply port, which will thus get recreated on next RPC. Otherwise, the next RPC will try to use it and probably receive a message that was for the interrupted RPC, and thus produce a -301 error (EMIG_REPLY_MISMATCH)... For instance, the testcase below always show that mach_port_destroy returns a -301 error: it actually gets the reply message of the raise call itself... Roland, do you agree on this? Samuel #include #include #include #include #include #include #include jmp_buf jb; void handle(int sig) { fprintf(stderr, "got it\n"); siglongjmp(jb, sig); } int main(void) { int res; int i; int err = 0; signal(SIGBUS, handle); if (!(res = sigsetjmp(jb, 1))) { res = raise(SIGBUS); if (res) perror("raise"); } else { res = mach_port_destroy(__mach_task_self(), MACH_PORT_NULL); if (res) fprintf(stderr,"%d\n", res); } return 0; } diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c index 3a62fb5..e535c4a 100644 --- a/hurd/sigunwind.c +++ b/hurd/sigunwind.c @@ -50,7 +50,8 @@ _hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val) *reply_port = MACH_PORT_DEAD; __mach_port_destroy (__mach_task_self (), port); } - *reply_port = scp->sc_reply_port; + if (scp->sc_reply_port) + __mach_port_destroy (__mach_task_self (), scp->sc_reply_port); } __spin_lock (&ss->lock);