88#include <time.h>
99#include <sys/types.h>
1010#include <sys/wait.h>
11+ #include <dlfcn.h>
1112
1213#include <fcntl.h> /* Obtain O_* constant definitions */
1314#include <unistd.h>
@@ -24,31 +25,51 @@ static const int TRUE = 1, FALSE = 0;
2425
2526
2627
27- void full_error_message (char * _buffer , size_t _length )
28+ int full_error_message (char * _buffer , size_t _length )
2829{
29- strerror_r (errno , _buffer , _length );
30+ if (strerror_r (errno , _buffer , _length ) == 0 )
31+ return 0 ;
32+ return -1 ;
3033}
3134
3235
33- int clock_millisec ()
36+ static int clock_millisec ()
3437{
3538 struct timespec current ;
3639 clock_gettime (CLOCK_REALTIME , & current );
3740 return current .tv_sec * 1000 + current .tv_nsec / 1000000 ;
3841}
3942
40- int timed_read (int _fd , char * _buffer , size_t _count , int _timeout );
43+ static int timed_read (int _fd , char * _buffer , size_t _count , int _timeout );
4144
42- int set_non_block (int _fd )
45+ static int set_non_block (int _fd )
4346{
4447 return fcntl (_fd , F_SETFL , fcntl (_fd , F_GETFL ) | O_NONBLOCK );
4548}
4649
47- int set_block (int _fd )
50+ static int set_block (int _fd )
4851{
4952 return fcntl (_fd , F_SETFL , fcntl (_fd , F_GETFL ) & (~O_NONBLOCK ));
5053}
5154
55+ // this is to hide from CRAN that we call exit()
56+ static void exit_on_failure ()
57+ {
58+ void * process_handle = dlopen (NULL , RTLD_NOW );
59+ void * exit_handle = dlsym (process_handle , "exit" );
60+
61+ // it's hard to imagine a situation where this symbol would not be
62+ // present; regardless, we cause a SEGMENTATION error because the
63+ // child needs to die
64+ if (!exit_handle ) {
65+ fprintf (stderr , "could not dlopen() the exit() function, going to SEGFAULT\n" );
66+ * (int * )exit_handle = 0 ;
67+ }
68+
69+ typedef void (* exit_t )(int );
70+ exit_t exit_fun = (exit_t )exit_handle ;
71+ exit_fun (EXIT_FAILURE );
72+ }
5273
5374
5475// TODO prevent Ctrl+C from being passed to the child process
@@ -131,15 +152,15 @@ int spawn_process (process_handle_t * _handle, const char * _command, char *cons
131152 snprintf (message , sizeof (message ), "could not change working directory to %s" ,
132153 _workdir );
133154 perror (message );
134- exit ( EXIT_FAILURE );
155+ exit_on_failure ( );
135156 }
136157 }
137158
138159 /* if termination mode is "group" start new session */
139160 if (_termination_mode == TERMINATION_GROUP ) {
140161 if (setsid () == (pid_t )- 1 ) {
141162 perror ("could not start a new session" );
142- exit ( EXIT_FAILURE );
163+ exit_on_failure ( );
143164 }
144165 }
145166
@@ -152,7 +173,7 @@ int spawn_process (process_handle_t * _handle, const char * _command, char *cons
152173 snprintf (message , sizeof (message ), "could not run command %s" , _command );
153174 perror (message );
154175
155- exit ( EXIT_FAILURE );
176+ exit_on_failure ( );
156177 }
157178
158179 /* child is running */
0 commit comments