@@ -42,7 +42,8 @@ static const char* _simulator_version = "1.0.0";
42
42
int data_len ;
43
43
int commfd ;
44
44
45
- static volatile sig_atomic_t sigint_called = false;
45
+ static volatile sig_atomic_t quitting = false;
46
+ static volatile sig_atomic_t hangup = false;
46
47
static int sockfd ;
47
48
48
49
static int get_usb_message_socket (uint8_t * input )
@@ -71,17 +72,28 @@ static void simulate_firmware_execution(const uint8_t* input)
71
72
usb_processing_process (usb_processing_hww ());
72
73
}
73
74
74
- static void _int_handler (int signum )
75
+ static void _quit_handler (int signum )
75
76
{
76
77
(void )signum ;
77
- sigint_called = true;
78
- close (sockfd );
78
+ quitting = true;
79
+ }
80
+
81
+ static void _hup_handler (int signum )
82
+ {
83
+ (void )signum ;
84
+ hangup = true;
79
85
}
80
86
81
87
int main (int argc , char * argv [])
82
88
{
83
- signal (SIGINT , _int_handler );
84
- // Default port number
89
+ struct sigaction psa ;
90
+ memset (& psa , 0 , sizeof (struct sigaction ));
91
+ psa .sa_handler = _quit_handler ;
92
+ sigaction (SIGINT , & psa , NULL );
93
+ sigaction (SIGTERM , & psa , NULL );
94
+ psa .sa_handler = _hup_handler ;
95
+ sigaction (SIGHUP , & psa , NULL );
96
+ // Default port number
85
97
int portno = 15423 ;
86
98
87
99
struct option long_options [] = {
@@ -162,11 +174,12 @@ int main(int argc, char* argv[])
162
174
while (1 ) {
163
175
if ((commfd = accept (sockfd , (struct sockaddr * )& serv_addr , (socklen_t * )& serv_addr_len )) <
164
176
0 ) {
165
- if (sigint_called ) {
166
- printf ("\nGot Ctrl-C, exiting\n" );
177
+ if (quitting ) {
178
+ printf ("\nGot signal, exiting\n" );
179
+ break ;
167
180
}
168
181
perror ("accept" );
169
- return 1 ;
182
+ break ;
170
183
}
171
184
printf ("Socket connection setup success\n" );
172
185
@@ -175,7 +188,33 @@ int main(int argc, char* argv[])
175
188
int temp_len ;
176
189
while (1 ) {
177
190
// Simulator polls for USB messages from client and then processes them
178
- if (!get_usb_message_socket (input )) break ;
191
+ if (get_usb_message_socket (input ) < 1 ) {
192
+ if (quitting ) {
193
+ printf ("\nGot term/int signal, exiting\n" );
194
+ // Using LINGER we force a TCP RST instead of graceful shutdown. Without this
195
+ // trick the port keeps being bound for 10s of seconds after the application has
196
+ // died, hindering future executions.
197
+ struct linger sol = {.l_onoff = 1 , .l_linger = 0 };
198
+ int res = setsockopt (commfd , SOL_SOCKET , SO_LINGER , & sol , sizeof (sol ));
199
+ if (res ) {
200
+ perror ("setsockopt" );
201
+ }
202
+ shutdown (commfd , SHUT_RDWR );
203
+ uint8_t buf [1024 ];
204
+ while (read (commfd , buf , sizeof (buf )) > 0 );
205
+ close (commfd );
206
+ goto after_main_loop ;
207
+ }
208
+ if (hangup ) {
209
+ hangup = false;
210
+ printf ("\nGot hangup signal, disconnecting\n" );
211
+ shutdown (commfd , SHUT_RDWR );
212
+ uint8_t buf [1024 ];
213
+ while (read (commfd , buf , sizeof (buf )) > 0 );
214
+ close (commfd );
215
+ }
216
+ break ;
217
+ }
179
218
simulate_firmware_execution (input );
180
219
181
220
// If the USB message to be sent from firmware is bigger than one packet,
@@ -196,5 +235,7 @@ int main(int argc, char* argv[])
196
235
printf ("Socket connection closed\n" );
197
236
printf ("Waiting for new clients, CTRL+C to shut down the simulator\n" );
198
237
}
238
+ after_main_loop :
239
+ close (sockfd );
199
240
return 0 ;
200
241
}
0 commit comments