-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess-api.c
More file actions
141 lines (118 loc) · 4.32 KB
/
process-api.c
File metadata and controls
141 lines (118 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* =============================================================================
process-api.c
This file is used to interact with the ./process executable. It contains
functions to send and receive messages to and from a process using pipes.
Author: David Sha
============================================================================= */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include "config.h"
#include "process-api.h"
void send_message(process_t *process, char *message, int length) {
/* Send a message to a process.
*/
if (write(process->fd[1], message, length) == FAILED) {
perror("write");
exit(EXIT_FAILURE);
}
}
void receive_message(process_t *process, char *message, int length) {
/* Receive a message from a process.
*/
if (read(process->parent_fd[0], message, length) == FAILED) {
perror("read");
exit(EXIT_FAILURE);
}
}
void check_process(process_t *process, char *simulation_time) {
/* Check that a process is still running by sending a message
and checking that the least significant bit of the message
is the same as the output from the process executable.
*/
char response[1] = {0};
receive_message(process, response, 1);
// check response is same as least significant bit of message
if (response[0] != simulation_time[BIG_ENDIAN_BYTES - 1]) {
printf("Error: Big Endian ordering did not pass correctly.\n");
exit(EXIT_FAILURE);
}
}
void start_process(process_t *process, char *simulation_time) {
/* Send the simulation time as a message to a process
to start the process.
Check that the process was started correctly by checking
that the least significant bit of the message is the same
as the output from the process executable.
*/
send_message(process, simulation_time, BIG_ENDIAN_BYTES);
// check that the process was started correctly
check_process(process, simulation_time);
}
void suspend_process(process_t *process, char *simulation_time) {
/* Send a simulation time as a message to a process. Then
suspend the process by sending a SIGTSTP signal.
*/
send_message(process, simulation_time, BIG_ENDIAN_BYTES);
// suspend process
int wstatus;
if (kill(process->pid, SIGTSTP) == FAILED) {
perror("kill");
exit(EXIT_FAILURE);
}
do {
if (waitpid(process->pid, &wstatus, WUNTRACED) == FAILED) {
perror("waitpid");
exit(EXIT_FAILURE);
}
} while (!WIFSTOPPED(wstatus));
}
void continue_process(process_t *process, char *simulation_time) {
/* Send a simulation time as a message to a process. Then
resume/continue the process by sending a SIGCONT signal.
Check that the process was continue correctly by checking
that the least significant bit of the message is the same
as the output from the process executable.
*/
send_message(process, simulation_time, BIG_ENDIAN_BYTES);
// continue process
if (kill(process->pid, SIGCONT) == FAILED) {
perror("kill");
exit(EXIT_FAILURE);
}
// check that the process was continue correctly
check_process(process, simulation_time);
}
char *terminate_process(process_t *process, char *simulation_time) {
/* Send a simulation time as a message to a process. Then
terminate the process by sending a SIGTERM signal.
Then read a 64 byte string from stdout of process executable
and include in execution transcript.
Return the string and free the process.
*/
send_message(process, simulation_time, BIG_ENDIAN_BYTES);
// terminate process
if (kill(process->pid, SIGTERM) == FAILED) {
perror("kill");
exit(EXIT_FAILURE);
}
// read 64 byte string from stdout of process executable
char *string = (char *)calloc(SHA256_LENGTH + 1, sizeof(char));
assert(string);
receive_message(process, string, SHA256_LENGTH);
// close pipes
if (close(process->fd[1]) == FAILED) {
perror("close");
exit(EXIT_FAILURE);
}
if (close(process->parent_fd[0]) == FAILED) {
perror("close");
exit(EXIT_FAILURE);
}
// free process
free(process);
return string;
}