Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[travis] detect linux as we should
[simgrid.git] / src / mc / mc_client.cpp
1 /* Copyright (c) 2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <error.h>
10
11 #include <sys/types.h>
12 #include <sys/socket.h>
13
14 #include <xbt/log.h>
15 #include <xbt/sysdep.h>
16 #include <xbt/mmalloc.h>
17
18 #include "mc_protocol.h"
19 #include "mc_client.h"
20
21 // We won't need those once the separation MCer/MCed is complete:
22 #include "mc_mmalloc.h"
23 #include "mc_ignore.h"
24 #include "mc_private.h" // MC_deadlock_check()
25 #include "mc_smx.h"
26
27 extern "C" {
28
29 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client, mc, "MC client logic");
30
31 mc_client_t mc_client;
32
33 void MC_client_init(void)
34 {
35   if (mc_client) {
36     XBT_WARN("MC_client_init called more than once.");
37     return;
38   }
39
40   char* fd_env = getenv(MC_ENV_SOCKET_FD);
41   if (!fd_env)
42     xbt_die("MC socket not found");
43
44   int fd = atoi(fd_env);
45   XBT_DEBUG("Model-checked application found socket FD %i", fd);
46
47   int type;
48   socklen_t socklen = sizeof(type);
49   if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) != 0)
50     xbt_die("Could not check socket type");
51   if (type != SOCK_DGRAM)
52     xbt_die("Unexpected socket type %i", type);
53   XBT_DEBUG("Model-checked application found expected socket type");
54
55   mc_client = xbt_new0(s_mc_client_t, 1);
56   mc_client->fd = fd;
57   mc_client->active = 1;
58 }
59
60 void MC_client_hello(void)
61 {
62   if (MC_protocol_hello(mc_client->fd) != 0)
63     xbt_die("Could not say hello the MC server");
64 }
65
66 void MC_client_send_message(void* message, size_t size)
67 {
68   if (MC_protocol_send(mc_client->fd, message, size))
69     xbt_die("Could not send message %i", (int) ((mc_message_t)message)->type);
70 }
71
72 void MC_client_send_simple_message(e_mc_message_type type)
73 {
74   if (MC_protocol_send_simple_message(mc_client->fd, type))
75     xbt_die("Could not send message %i", type);
76 }
77
78 void MC_client_handle_messages(void)
79 {
80   while (1) {
81     XBT_DEBUG("Waiting messages from model-checker");
82
83     char message_buffer[MC_MESSAGE_LENGTH];
84     ssize_t s;
85     if ((s = MC_receive_message(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) < 0)
86       xbt_die("Could not receive commands from the model-checker");
87
88     s_mc_message_t message;
89     if ((size_t) s < sizeof(message))
90       xbt_die("Received message is too small");
91     memcpy(&message, message_buffer, sizeof(message));
92     switch (message.type) {
93
94     case MC_MESSAGE_DEADLOCK_CHECK:
95       {
96         int result = MC_deadlock_check();
97         s_mc_int_message_t answer;
98         answer.type = MC_MESSAGE_DEADLOCK_CHECK_REPLY;
99         answer.value = result;
100         if (MC_protocol_send(mc_client->fd, &answer, sizeof(answer)))
101           xbt_die("Could not send response");
102       }
103       break;
104
105     case MC_MESSAGE_CONTINUE:
106       return;
107
108     case MC_MESSAGE_SIMCALL_HANDLE:
109       {
110         s_mc_simcall_handle_message_t message;
111         if (s != sizeof(message))
112           xbt_die("Unexpected size for SIMCALL_HANDLE");
113         memcpy(&message, message_buffer, sizeof(message));
114         smx_process_t process = SIMIX_process_from_PID(message.pid);
115         if (!process)
116           xbt_die("Invalid pid %lu", (unsigned long) message.pid);
117         SIMIX_simcall_handle(&process->simcall, message.value);
118         MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
119       }
120       break;
121
122     default:
123       xbt_die("%s received unexpected message %s (%i)",
124         MC_mode_name(mc_mode),
125         MC_message_type_name(message.type),
126         message.type
127       );
128     }
129   }
130 }
131
132 void MC_client_main_loop(void)
133 {
134   while (1) {
135     MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
136     MC_client_handle_messages();
137     MC_wait_for_requests();
138   }
139 }
140
141 }