[OpenVMS, CRTL, V8.3-1H1, V8.4] sigsetjmp and siglongjmp working only once
PRODUCT: HP C RTL V8.3-01 HP C RTL V8.4-00
OP/SYS: OpenVMS IA64 V8.3-1H1 and above
COMPONENT: sigsetjmp and siglongjmp
SOURCE: Philippe Vouters Fontainebleau/France
LOW-COST HIGH-TECH: http://techno-star.fr
SYMPTOM(S) or PROBLEM(S): sigsetjmp and siglongjmp run correctly only once on an OpenVMS system.
SOLUTION or RESPONSE: A sigsetjmp and siglongjmp pair works only once on OpenVMS V8.3-1H1 and above systems. If you are porting Unix code onto OpenVMS, your Unix code algorythm being close to what is in the PROGRAM section of this document, you should consider delay your port work until this problem is correctly addressed by the HP C RTL.
WORKAROUND or ALTERNATIVE: No workaround using sigsetjmp and siglongjmp. This is just a VMS incompatibility of the C RTL with the Unix world.
PROGRAM OUTPUT: The source code in the PROGRAM section of this document behaves the following: OpenVMS IA64 V8.3-1H1 and above systems: $ cc signal_unix.c $ link signal_unix.c $ spawn/nowait run signal_unix %DCL-S-SPAWNED, process PHV_58176 spawned $ Type in $ kill -USR2 539359686 $ cc kill $ link kill $ kill :== $phv:[phv]kill $ kill THESEE PHV_58176 SIGUSR2 In handlerSigusr2 for pid=539359686 Returned to main $ kill THESEE PHV_58176 SIGUSR2 $ kill THESEE PHV_58176 SIGUSR2 Linux Fedora 15 system: $ cc -o signal_unix signal_unix.c $ ./signal_unix & [1] 25309 $ Type in $ kill -USR2 25309 $ kill -USR2 25309 In handlerSigusr2 for pid=25309 Returned to main $ kill -USR2 25309 In handlerSigusr2 for pid=25309 Returned to main $ kill -USR2 25309 In handlerSigusr2 for pid=25309 Returned to main $ kill -USR2 25309 In handlerSigusr2 for pid=25309 Returned to main
ANALYSIS: The Linux Fedora 15 behavior of the code in the PROGRAM section is what is expected. On OpenVMS, the C RTL seems to save the pause() call stack in the environment_buffer variable at the second sigsetjmp call invocation. Hence, the siglongjmp seemlingly resuming the program into the pause() statement after the second external kill.
PROGRAM: /* * Copyright (C) 2011 by Philippe.Vouters@laposte.net * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <setjmp.h> #include <sys/types.h> #include <unistd.h> sigjmp_buf environment_buffer; pid_t main_pid; struct sigaction sa; static void handlerSIGUSR2(int); static void trap_signals(struct sigaction *sa) { sa->sa_handler = handlerSIGUSR2; sigemptyset(&sa->sa_mask); sa->sa_flags = SA_RESETHAND; if(sigaction(SIGUSR2, sa, 0)){ perror("sigaction"); exit(EXIT_FAILURE); } } static void handlerSIGUSR2(int ArgIgnore){ printf ("In handlerSigusr2 for pid=%1u\n",getpid()); trap_signals(&sa); siglongjmp (environment_buffer,1) ; return; } int main(int argc, char **argv){ pid_t pid; main_pid=getpid(); trap_signals(&sa); printf("Type in $ kill -USR2 %1u\n", main_pid); if (sigsetjmp(environment_buffer,1) == 1) printf ("Returned to main\n"); pause(); return 0; }