Compare View

switch
from
...
to
 
Commits (2)
anubis_dev/vm/SConstruct
... ... @@ -38,7 +38,7 @@ static = ARGUMENTS.get('STATIC', 0)
38 38  
39 39 maj_version = 1
40 40 min_version = 19
41   -rel_version = 14
  41 +rel_version = 15
42 42  
43 43 if openssl == 1 and wolfssl == 1:
44 44 print("Error: OSSL and WSSL can't be set together ")
... ... @@ -310,7 +310,7 @@ main_src = [os.path.join('build', x) for x in Split("""
310 310 vmint.cpp vmalloc.cpp vm.cpp vmtools.cpp graphics.cpp sslstuff.cpp time.c
311 311 AnubisAllocator.cpp AnubisFileLocker.cpp AnubisProcess.cpp
312 312 syscall.cpp syscall32.cpp serialize.cpp Profiling.cpp debugger.cpp Library.cpp
313   - dynamic_module.cpp boyer_moore.cpp
  313 + dynamic_module.cpp boyer_moore.cpp vm_socket.cpp
314 314 """)]
315 315 if sqlapi:
316 316 main_src.append(os.path.join('build', 'dbapi_tools.cpp'))
... ...
anubis_dev/vm/src/AnubisProcess.cpp
... ... @@ -423,9 +423,11 @@ AnubisProcessList::~AnubisProcessList(void)
423 423  
424 424 void AnubisProcess::RegisterFDIn(int fd)
425 425 {
  426 +
426 427 m_fds_in.AddItemUnique((void *)fd);
427 428 FD_SET(fd, &descriptors_waited_for_input);
428 429 m_status = waiting_for_event;
  430 +
429 431 }
430 432  
431 433 void AnubisProcess::RegisterFDOut(int fd)
... ...
anubis_dev/vm/src/anbexec.cpp
... ... @@ -31,6 +31,7 @@
31 31 #include "MultiPath.h"
32 32 #include "../../../third_dev/sqlite3/sqlite3.h"
33 33 #include "perf.h"
  34 +#include "vm_socket.h"
34 35  
35 36 #if defined (_LINUX_) || (__BEOS__)
36 37 #include <sys/time.h>
... ... @@ -204,7 +205,7 @@ struct timeval next_tick;
204 205 U32 alarm_set;
205 206 U32 hpc_option = 0;
206 207 U32 show_waiting_descriptors = 0;
207   -U32 show_module_loading = 1;
  208 +U32 show_module_loading = 0;
208 209  
209 210 extern U32 anubis_empty_string;
210 211 extern U32 anubis_empty_byte_array;
... ... @@ -728,7 +729,7 @@ U32 avenrun[3];
728 729 static void calc_load(U32 ticks, U32 active_tasks /* fixed-point */, bigtime_t * slice)
729 730 {
730 731 static int32_t count = LOAD_FREQ;
731   - //U32 active_tasks_fixed = active_tasks << FSHIFT; /* fixed-point */
  732 + //U32 active_tasks_fixed = active_tasks << FSHIFT; /* fixed-point */
732 733  
733 734 count -= ticks;
734 735 if (count < 0) {
... ... @@ -741,7 +742,7 @@ static void calc_load(U32 ticks, U32 active_tasks /* fixed-point */, bigtime_t *
741 742 //printf("Load = %d %d %d %d \n", active_tasks, avenrun[0], avenrun[1], avenrun[2]);
742 743 U32 nbProcess = TheAnubisProcessList->GetCount();
743 744 AnubisProcess * processItem = NULL;
744   - U32 ul_slice = (U32)((*slice << FSHIFT) / 1000000); // in seconds
  745 + U32 ul_slice = (U32)((*slice << FSHIFT) / 1000000); // in seconds
745 746 U32 sum_load = 0;
746 747 float sum = 0.0f;
747 748 for (U32 i = 0; i < nbProcess; i++)
... ... @@ -905,7 +906,7 @@ void schedul(void)
905 906 FD_ZERO(&descriptors_waited_for_output);
906 907  
907 908 while(!quitingVM)
908   - {
  909 + {
909 910 if (TheAnubisProcessList->GetCount() == 0)
910 911 {
911 912 #ifdef record_allocations
... ... @@ -965,20 +966,21 @@ void schedul(void)
965 966  
966 967 TheAnubisProcessList->SetRunningProcess(processItem);
967 968 AnubisProcess::anbStatus st = processItem->GetStatus();
  969 +
968 970 switch (st)
969 971 {
970   - case CM::AnubisProcess::machine_not_used:
  972 + case CM::AnubisProcess::machine_not_used:
971 973 break;
972 974  
973 975 case AnubisProcess::running:
974   - #if 0
  976 + #if 0
975 977 { /* debugging tool */
976 978 U8 p = processItem->GetPriority();
977 979 U32 c = compute_credit(max_running_priority,p);
978 980 if (p != 255) { printf("<%d|%d>",p,c); fflush(stdout); }
979 981 }
980 982 #endif
981   -
  983 +
982 984 // run this machine for as many steps as its credit allows:
983 985 steps = processItem->RunMachine(compute_credit(max_running_priority,processItem->GetPriority())) ;
984 986 break;
... ... @@ -1055,7 +1057,7 @@ void schedul(void)
1055 1057 bigtime_t t1 = system_time();
1056 1058 processItem->PerfSumTime(t1 - perf_t0);
1057 1059 perf_sum += t1 - perf_t0;
1058   - }
  1060 + }
1059 1061  
1060 1062 st = processItem->GetStatus();
1061 1063  
... ... @@ -1092,7 +1094,7 @@ void schedul(void)
1092 1094 }
1093 1095  
1094 1096 //printf("1"); fflush(stdout);
1095   -
  1097 +
1096 1098 if (running_machines == 0) // no machine running (nor waiting)
1097 1099 {
1098 1100 //printf("2"); fflush(stdout);
... ... @@ -1126,62 +1128,62 @@ void schedul(void)
1126 1128 //printf("3"); fflush(stdout);
1127 1129  
1128 1130 // Here is a test performed only if anbexec got the --hpc option
1129   - if(hpc_option)
1130   - {
1131   - hpc++;
1132   - // print this only 1/256 passes because hpc is a byte (8bit) and
1133   - // become 0 the 256th time on incrementation
1134   - if (hpc == 0)
1135   - {
1136   - U32 nbProc = TheAnubisProcessList->GetCount();
1137   - AnubisProcess * proc;
1138   - gettimeofday(&current_time,NULL);
1139   -
1140   - printf("(%u processes) ",nbProc);
1141   - printf("%lu:%lu ",current_time.tv_sec, current_time.tv_usec);
1142   - //for (i = nbProc - 1; i != ~(U32)0; i--)
1143   - for (i = 0; i < nbProc; i++)
1144   - {
1145   - char *anbst = (char *)"??";
1146   - proc = TheAnubisProcessList->GetProcessAt(i);
1147   - AnubisProcess::anbStatus st = proc->GetStatus();
1148   -
1149   - if (st == AnubisProcess::machine_not_used) anbst = (char *)"nu";
1150   - if (st == AnubisProcess::running) anbst = (char *)"ru";
1151   - if (st == AnubisProcess::waiting_for_event) anbst = (char *)"we";
1152   - if (st == AnubisProcess::waiting_for_condition) anbst = (char *)"wc";
1153   - if (st == AnubisProcess::waiting_for_completion) anbst = (char *)"wp";
1154   - if (st == AnubisProcess::finished) anbst = (char *)"fi";
1155   - if (st == AnubisProcess::need_bigger_stack) anbst = (char *)"ns";
1156   - if (st == AnubisProcess::need_more_memory) anbst = (char *)"nm";
1157   -
1158   - //information regarding the PID, Status, Relative IP
1159   - printf("%u%s[%u|%u]", proc->GetPid(),anbst,find_module_index(proc->GetIP()),
1160   - relative_IP(proc->GetIP()));
1161   -
1162   - //information regarding time to wait if need
1163   - if (st == AnubisProcess::waiting_for_condition)
1164   - {
1165   - if (timeval_substract(&time_to_wait, proc->GetAlarm(), &current_time))
1166   - {
1167   - /* negative! don't waits */
1168   - time_to_wait.tv_sec = 0;
1169   - time_to_wait.tv_usec = 0;
1170   - }
1171   - //add the alarm to go
1172   - printf("%lu:%lu ",time_to_wait.tv_sec, time_to_wait.tv_usec);
1173   - }
1174   - else
1175   - {
1176   - //add trailing space
1177   - printf(" ");
1178   - }
1179   - }
1180   - printf(" \n");
1181   - fflush(stdout);
1182   - }
1183   - }
1184   -
  1131 + if(hpc_option)
  1132 + {
  1133 + hpc++;
  1134 + // print this only 1/256 passes because hpc is a byte (8bit) and
  1135 + // become 0 the 256th time on incrementation
  1136 + if (hpc == 0)
  1137 + {
  1138 + U32 nbProc = TheAnubisProcessList->GetCount();
  1139 + AnubisProcess * proc;
  1140 + gettimeofday(&current_time,NULL);
  1141 +
  1142 + printf("(%u processes) ",nbProc);
  1143 + printf("%lu:%lu ",current_time.tv_sec, current_time.tv_usec);
  1144 + //for (i = nbProc - 1; i != ~(U32)0; i--)
  1145 + for (i = 0; i < nbProc; i++)
  1146 + {
  1147 + char *anbst = (char *)"??";
  1148 + proc = TheAnubisProcessList->GetProcessAt(i);
  1149 + AnubisProcess::anbStatus st = proc->GetStatus();
  1150 +
  1151 + if (st == AnubisProcess::machine_not_used) anbst = (char *)"nu";
  1152 + if (st == AnubisProcess::running) anbst = (char *)"ru";
  1153 + if (st == AnubisProcess::waiting_for_event) anbst = (char *)"we";
  1154 + if (st == AnubisProcess::waiting_for_condition) anbst = (char *)"wc";
  1155 + if (st == AnubisProcess::waiting_for_completion) anbst = (char *)"wp";
  1156 + if (st == AnubisProcess::finished) anbst = (char *)"fi";
  1157 + if (st == AnubisProcess::need_bigger_stack) anbst = (char *)"ns";
  1158 + if (st == AnubisProcess::need_more_memory) anbst = (char *)"nm";
  1159 +
  1160 + //information regarding the PID, Status, Relative IP
  1161 + printf("%u%s[%u|%u]", proc->GetPid(),anbst,find_module_index(proc->GetIP()),
  1162 + relative_IP(proc->GetIP()));
  1163 +
  1164 + //information regarding time to wait if need
  1165 + if (st == AnubisProcess::waiting_for_condition)
  1166 + {
  1167 + if (timeval_substract(&time_to_wait, proc->GetAlarm(), &current_time))
  1168 + {
  1169 + /* negative! don't waits */
  1170 + time_to_wait.tv_sec = 0;
  1171 + time_to_wait.tv_usec = 0;
  1172 + }
  1173 + //add the alarm to go
  1174 + printf("%lu:%lu ",time_to_wait.tv_sec, time_to_wait.tv_usec);
  1175 + }
  1176 + else
  1177 + {
  1178 + //add trailing space
  1179 + printf(" ");
  1180 + }
  1181 + }
  1182 + printf(" \n");
  1183 + fflush(stdout);
  1184 + }
  1185 + }
  1186 +
1185 1187  
1186 1188 // because of how these numbers are computed above, we must have:
1187 1189 // assert(waiting_machines <= running_machines);
... ... @@ -1231,28 +1233,28 @@ void schedul(void)
1231 1233 processItem = TheAnubisProcessList->GetProcessAt(i);
1232 1234 if (processItem->GetStatus() == AnubisProcess::waiting_for_condition)
1233 1235 {
1234   - if (alarm_set)
1235   - {
1236   - /* not the first waiting_for_condition machine */
1237   - /* the process alarm is smaller than current alarm */
1238   - if (timevalless(processItem->GetAlarm(),&alarm_time))
1239   - {
1240   - alarm_time.tv_sec = processItem->GetAlarm()->tv_sec;
1241   - alarm_time.tv_usec = processItem->GetAlarm()->tv_usec;
1242   - }
1243   - }
1244   - else
1245   - {
1246   - /* this is the first waiting_for_condition machine */
1247   - alarm_time.tv_sec = processItem->GetAlarm()->tv_sec;
1248   - alarm_time.tv_usec = processItem->GetAlarm()->tv_usec;
1249   - alarm_set = 1;
1250   - }
1251   - /* blah blah */
1252   - if (show_waiting_descriptors)
1253   - {
1254   - LOGINFO("machine %d is waiting for condition.\n",i);
1255   - }
  1236 + if (alarm_set)
  1237 + {
  1238 + /* not the first waiting_for_condition machine */
  1239 + /* the process alarm is smaller than current alarm */
  1240 + if (timevalless(processItem->GetAlarm(),&alarm_time))
  1241 + {
  1242 + alarm_time.tv_sec = processItem->GetAlarm()->tv_sec;
  1243 + alarm_time.tv_usec = processItem->GetAlarm()->tv_usec;
  1244 + }
  1245 + }
  1246 + else
  1247 + {
  1248 + /* this is the first waiting_for_condition machine */
  1249 + alarm_time.tv_sec = processItem->GetAlarm()->tv_sec;
  1250 + alarm_time.tv_usec = processItem->GetAlarm()->tv_usec;
  1251 + alarm_set = 1;
  1252 + }
  1253 + /* blah blah */
  1254 + if (show_waiting_descriptors)
  1255 + {
  1256 + LOGINFO("machine %d is waiting for condition.\n",i);
  1257 + }
1256 1258 }
1257 1259 }
1258 1260 #if 1
... ... @@ -1303,157 +1305,215 @@ void schedul(void)
1303 1305 //time_to_wait.tv_usec = 0;
1304 1306  
1305 1307 //memcpy(&rfds,&descriptors_waited_for_input,sizeof(fd_set));
1306   -
  1308 +FD_ZERO(&rfds);
  1309 +FD_ZERO(&wfds);
  1310 +FD_ZERO(&efds);
1307 1311 //make copy of descriptors, because select will destroy the list
1308 1312 memcpy(&rfds, &descriptors_waited_for_input, sizeof(fd_set));
1309 1313 memcpy(&wfds, &descriptors_waited_for_output, sizeof(fd_set));
1310 1314 FD_ZERO(&efds);
1311 1315  
1312   - //printf("SELECT timeout=%ld.%06ld\n", (long)time_to_wait.tv_sec, (long)time_to_wait.tv_usec);
1313   - for (int fd = 0; fd < FD_SETSIZE; fd++)
1314   - {
1315   - if (FD_ISSET(fd, &descriptors_waited_for_input) ||
1316   - FD_ISSET(fd, &descriptors_waited_for_output))
1317   - {
1318   - errno = 0;
1319   - int r = fcntl(fd, F_GETFL);
1320   -
1321   - if (r == -1)
1322   - {
1323   - printf("INVALID FD IN SELECT SET: fd=%d errno=%d (%s)\n",
1324   - fd,
1325   - errno,
1326   - strerror(errno));
1327   - }
1328   - }
1329   - }
1330   -
  1316 + //printf("SELECT timeout=%ld.%06ld\n", (long)time_to_wait.tv_sec, (long)time_to_wait.tv_usec);
  1317 + for (int fd = 0; fd < FD_SETSIZE; fd++)
  1318 + {
  1319 + if (FD_ISSET(fd, &descriptors_waited_for_input) ||
  1320 + FD_ISSET(fd, &descriptors_waited_for_output))
  1321 + {
  1322 +#ifdef WIN32
  1323 + int socket_type = 0;
  1324 + int socket_type_len = sizeof(socket_type);
  1325 +
  1326 + int r = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, (char *)&socket_type, &socket_type_len);
  1327 +
  1328 + if (r == SOCKET_ERROR)
  1329 + {
  1330 + int error = WSAGetLastError();
  1331 +
  1332 + if (error == WSAENOTSOCK)
  1333 + {
  1334 + printf("INVALID SOCKET IN SELECT SET: fd=%d WSAerror=%d\n", fd, error);
  1335 + }
  1336 + }
  1337 +#else
  1338 + errno = 0;
  1339 + int r = fcntl(fd, F_GETFL);
  1340 +
  1341 + if (r == -1)
  1342 + {
  1343 + printf("INVALID FD IN SELECT SET: fd=%d errno=%d (%s)\n", fd, errno, strerror(errno));
  1344 + }
  1345 +#endif
  1346 + }
  1347 + }
  1348 +
1331 1349 /****************** The core ****************/
1332   -
1333   - select_result = select(FD_SETSIZE,
  1350 +
  1351 + select_result = vm_socket_select(FD_SETSIZE,
1334 1352 &rfds,
1335 1353 &wfds,
1336 1354 NULL,
1337 1355 alarm_set ? &time_to_wait : NULL);
1338   -
1339   - /****************** The core ****************/
1340   -
1341   -#if 0
1342   - if (select_result > 0)
1343   - {
1344   - int ready_count = 0;
1345   - /// printf("SELECT result=%d\n", select_result);
1346   -
1347   -
1348   -
1349   - for (int fd = 0; fd < FD_SETSIZE; fd++)
1350   - {
1351   - if (FD_ISSET(fd, &rfds))
1352   - {
1353   - ready_count++;
1354   - }
1355   -
1356   - if (FD_ISSET(fd, &wfds))
1357   - {
1358   - ready_count++;
1359   - }
1360   - }
1361   -
1362   - printf(" ready_count=%d\n", ready_count);
1363   - }
1364   - else if (select_result == 0)
1365   - {
1366   - //printf("select() timeout\n");
1367   - }
1368   - else
  1356 +
  1357 + /****************** The core ****************/
  1358 +
  1359 +
  1360 +#if 0
  1361 + if (select_result > 0)
  1362 + {
  1363 + int ready_count = 0;
  1364 + /// printf("SELECT result=%d\n", select_result);
  1365 +
  1366 +
  1367 +
  1368 + for (int fd = 0; fd < FD_SETSIZE; fd++)
  1369 + {
  1370 + if (FD_ISSET(fd, &rfds))
  1371 + {
  1372 + ready_count++;
  1373 + }
  1374 +
  1375 + if (FD_ISSET(fd, &wfds))
  1376 + {
  1377 + ready_count++;
  1378 + }
  1379 + }
  1380 +
  1381 + printf(" ready_count=%d\n", ready_count);
  1382 + }
  1383 + else if (select_result == 0)
  1384 + {
  1385 + //printf("select() timeout\n");
  1386 + }
  1387 + else
1369 1388 #endif
1370   -
1371   - if (select_result <0)
1372   - {
1373   - int err = errno;
1374   - if(err == EINTR)
1375   - {
1376   - continue;
1377   - }
1378   - if (err == EBADF)
1379   - {
1380   - for (int fd = 0; fd < FD_SETSIZE; fd++)
1381   - {
  1389 +
  1390 + if (select_result <0)
  1391 + {
  1392 +
  1393 + int err = LAST_SOCKET_ERROR;
  1394 +
  1395 + if (err == EINTR)
  1396 + {
  1397 + continue;
  1398 + }
  1399 +#ifdef WIN32
  1400 + /*
  1401 + * On Windows, an invalid entry in the fd_set is reported
  1402 + * by Winsock as WSAENOTSOCK.
  1403 + */
  1404 + if (err == WSAENOTSOCK)
  1405 + {
  1406 + for (int fd = 0; fd < FD_SETSIZE; fd++)
  1407 + {
  1408 + bool in_set = FD_ISSET(fd, &descriptors_waited_for_input);
  1409 + bool out_set = FD_ISSET(fd, &descriptors_waited_for_output);
  1410 +
  1411 + if (!in_set && !out_set)
  1412 + continue;
  1413 +
  1414 + int socket_type = 0;
  1415 + int socket_type_len = sizeof(socket_type);
  1416 +
  1417 + int r = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, (char *)&socket_type, &socket_type_len);
  1418 +
  1419 + if (r == SOCKET_ERROR)
  1420 + {
  1421 + int socket_error = WSAGetLastError();
  1422 + if (socket_error == WSAENOTSOCK)
  1423 + {
  1424 + LOGERROR("scheduler: INVALID SOCKET IN SELECT SET: fd=%d\n", fd);
  1425 + cleanup_invalid_fd(fd);
  1426 + }
  1427 + }
  1428 + }
  1429 +
  1430 + continue;
  1431 + }
  1432 +
  1433 + LOGERROR("scheduler: select() -> %d\n", err);
  1434 +
  1435 +#else
  1436 +
  1437 + if (err == EBADF)
  1438 + {
  1439 + for (int fd = 0; fd < FD_SETSIZE; fd++)
  1440 + {
1382 1441 bool in_set = FD_ISSET(fd, &descriptors_waited_for_input);
1383 1442 bool out_set = FD_ISSET(fd, &descriptors_waited_for_output);
1384 1443  
1385   - if (!in_set && !out_set)
1386   - continue;
  1444 + if (!in_set && !out_set)
  1445 + continue;
1387 1446  
1388   - errno = 0;
  1447 + errno = 0;
1389 1448  
1390 1449 if (fcntl(fd, F_GETFL) == -1 && errno == EBADF)
1391 1450 {
1392 1451 LOGERROR("scheduler: INVALID FD IN SELECT SET: fd=%d\n", fd);
1393 1452 cleanup_invalid_fd(fd);
1394 1453 }
1395   - }
1396   -
1397   - continue;
1398   - }
1399   -
1400   - LOGERROR("scheduler: select() -> %d (%s)\n", err, strerror(err));
1401   - //usleep(1000);
1402   - continue;
1403   - }
1404   -
1405   -
1406   - if (select_result > 0)
1407   - {
1408   - /// printf("Select result %d \n",select_result);
1409   -
1410   - nbProcess = TheAnubisProcessList->GetCount();
1411   -
1412   - for (i = 0; i < nbProcess; i++)
1413   - {
1414   - processItem = TheAnubisProcessList->GetProcessAt(i);
1415   - //skip processes who not waiting for event
1416   - if (processItem->GetStatus() != AnubisProcess::waiting_for_event)
1417   - {
1418   - continue;
1419   - }
1420   - else
1421   - {
1422   - //check if the fd is part of the process
1423   - bool process_ready = false;
1424   -
1425   - //Check the input
1426   - for(U32 j = processItem->m_fds_in.GetCount(); j > 0; j--)
1427   - {
1428   - U32 fd = (U32)processItem->m_fds_in.ItemAt(j-1);
1429   - if(FD_ISSET(fd, &rfds))
1430   - {
1431   - processItem->m_fds_in.RemoveItem((void *)fd);
1432   - FD_CLR(fd, &descriptors_waited_for_input);
1433   - process_ready = true;
1434   - }
1435   - }
1436   -
1437   - //now checking the output
1438   - for (U32 j = processItem->m_fds_out.GetCount(); j > 0; j--)
1439   - {
1440   - U32 fd = (U32)processItem->m_fds_out.ItemAt(j-1);
1441   - if (FD_ISSET(fd, &wfds))
1442   - {
1443   - processItem->m_fds_out.RemoveItem((void *)fd);
1444   - FD_CLR(fd, &descriptors_waited_for_output);
1445   - process_ready = true;
1446   - }
1447   - }
1448   -
1449   - if(process_ready)
1450   - {
1451   - processItem->SetStatus(AnubisProcess::running);
1452   - }
1453   - }
  1454 + }
  1455 +
  1456 + continue;
  1457 + }
  1458 +
  1459 + LOGERROR("scheduler: select() -> %d (%s)\n", err, strerror(err));
  1460 +#endif
  1461 + //usleep(1000);
  1462 + continue;
  1463 + }
  1464 +
  1465 +
  1466 + if (select_result > 0)
  1467 + {
  1468 + /// printf("Select result %d \n",select_result);
  1469 +
  1470 + nbProcess = TheAnubisProcessList->GetCount();
  1471 +
  1472 + for (i = 0; i < nbProcess; i++)
  1473 + {
  1474 + processItem = TheAnubisProcessList->GetProcessAt(i);
  1475 + //skip processes who not waiting for event
  1476 + if (processItem->GetStatus() != AnubisProcess::waiting_for_event)
  1477 + {
  1478 + continue;
  1479 + }
  1480 + else
  1481 + {
  1482 + //check if the fd is part of the process
  1483 + bool process_ready = false;
  1484 +
  1485 + //Check the input
  1486 + for(U32 j = processItem->m_fds_in.GetCount(); j > 0; j--)
  1487 + {
  1488 + U32 fd = (U32)processItem->m_fds_in.ItemAt(j-1);
  1489 + if(FD_ISSET(fd, &rfds))
  1490 + {
  1491 + processItem->m_fds_in.RemoveItem((void *)fd);
  1492 + FD_CLR(fd, &descriptors_waited_for_input);
  1493 + process_ready = true;
  1494 + }
  1495 + }
  1496 +
  1497 + //now checking the output
  1498 + for (U32 j = processItem->m_fds_out.GetCount(); j > 0; j--)
  1499 + {
  1500 + U32 fd = (U32)processItem->m_fds_out.ItemAt(j-1);
  1501 + if (FD_ISSET(fd, &wfds))
  1502 + {
  1503 + processItem->m_fds_out.RemoveItem((void *)fd);
  1504 + FD_CLR(fd, &descriptors_waited_for_output);
  1505 + process_ready = true;
  1506 + }
  1507 + }
  1508 +
  1509 + if(process_ready)
  1510 + {
  1511 + processItem->SetStatus(AnubisProcess::running);
  1512 + }
  1513 + }
1454 1514  
1455 1515 }
1456   - }
  1516 + }
1457 1517 }
1458 1518 /* We are here because there is at least one running machine
1459 1519 that is not waiting. Consequently, we must continue from
... ... @@ -1577,8 +1637,8 @@ void OutputProfiling()
1577 1637 FunctionCall * parent = fCall->Parent();
1578 1638 fCall->Return();
1579 1639 fCall = parent;
1580   - }
1581   - }
  1640 + }
  1641 + }
1582 1642  
1583 1643 U32 countProfilingFunctions = AnubisProcess::GetFunctionsList().GetCount();
1584 1644 if(countProfilingFunctions > 0)
... ... @@ -1586,30 +1646,30 @@ void OutputProfiling()
1586 1646 bigtime_t full_time = system_time() - profiling_start_time;
1587 1647 if(profile_output_format == "csv")
1588 1648 {
1589   - fprintf(stderr, "Function"); fprintf(stderr, "%s", csv_separator.Cstr());
1590   - fprintf(stderr, "Offset"); fprintf(stderr, "%s", csv_separator.Cstr());
1591   - fprintf(stderr, "Hits"); fprintf(stderr, "%s", csv_separator.Cstr());
1592   - fprintf(stderr, "Time (excl. children)"); fprintf(stderr, "%s", csv_separator.Cstr());
1593   - fprintf(stderr, "Time %%"); fprintf(stderr, "%s", csv_separator.Cstr());
1594   - fprintf(stderr, "Max (inc. children)"); fprintf(stderr, "%s", csv_separator.Cstr());
  1649 + fprintf(stderr, "Function"); fprintf(stderr, "%s", csv_separator.Cstr());
  1650 + fprintf(stderr, "Offset"); fprintf(stderr, "%s", csv_separator.Cstr());
  1651 + fprintf(stderr, "Hits"); fprintf(stderr, "%s", csv_separator.Cstr());
  1652 + fprintf(stderr, "Time (excl. children)"); fprintf(stderr, "%s", csv_separator.Cstr());
  1653 + fprintf(stderr, "Time %%"); fprintf(stderr, "%s", csv_separator.Cstr());
  1654 + fprintf(stderr, "Max (inc. children)"); fprintf(stderr, "%s", csv_separator.Cstr());
1595 1655 fprintf(stderr, "Max %%");
1596 1656 fprintf(stderr, "\n");
1597 1657 for(U32 i = 0; i < countProfilingFunctions; i++)
1598 1658 {
1599 1659 FunctionSummary * sum = AnubisProcess::GetFunctionsList()[i];
1600   - fprintf(stderr, "\"%s\"", sum->Name()); fprintf(stderr, "%s", csv_separator.Cstr());
1601   - fprintf(stderr, "%d", sum->Label()); fprintf(stderr, "%s", csv_separator.Cstr());
  1660 + fprintf(stderr, "\"%s\"", sum->Name()); fprintf(stderr, "%s", csv_separator.Cstr());
  1661 + fprintf(stderr, "%d", sum->Label()); fprintf(stderr, "%s", csv_separator.Cstr());
1602 1662 fprintf(stderr, "%d", (int)sum->Hits());
1603 1663 fprintf(stderr, "%s", csv_separator.Cstr());
1604   - fprintf(stderr, "%.6f", (float)sum->TotalTimeWithoutChildren() / 1000000.0f);
  1664 + fprintf(stderr, "%.6f", (float)sum->TotalTimeWithoutChildren() / 1000000.0f);
1605 1665 fprintf(stderr, "%s", csv_separator.Cstr());
1606 1666 fprintf(stderr, "%.1f", (float)sum->TotalTimeWithoutChildren() / full_time * 100.0f);
1607 1667 fprintf(stderr, "%s", csv_separator.Cstr());
1608   - fprintf(stderr, "%.6f", (float)sum->MaxTimeWithChildren() / 1000000.0f); fprintf(stderr, "%s", csv_separator.Cstr());
1609   - fprintf(stderr, "%.1f", (float)sum->MaxTimeWithChildren() / full_time * 100.0f); fprintf(stderr, "\n");
1610   - }
  1668 + fprintf(stderr, "%.6f", (float)sum->MaxTimeWithChildren() / 1000000.0f); fprintf(stderr, "%s", csv_separator.Cstr());
  1669 + fprintf(stderr, "%.1f", (float)sum->MaxTimeWithChildren() / full_time * 100.0f); fprintf(stderr, "\n");
  1670 + }
1611 1671 }
1612   - else // text format by default
  1672 + else // text format by default
1613 1673 {
1614 1674 fprintf(stderr, "*** PROFILING DATA ***\n");
1615 1675 fprintf(stderr, "*** Full executing time = %.3f s\n", (float)full_time / 1000000.0f);
... ... @@ -1623,8 +1683,8 @@ void OutputProfiling()
1623 1683 (float)sum->TotalTimeWithoutChildren() / full_time * 100.0f);
1624 1684 fprintf(stderr, " max (including children) = %.3f s (%.1f%%)\n", (float)sum->MaxTimeWithChildren() / 1000000.0f,
1625 1685 (float)sum->MaxTimeWithChildren() / full_time * 100.0f);
1626   - }
1627   - }
  1686 + }
  1687 + }
1628 1688 }
1629 1689 }
1630 1690  
... ... @@ -1657,23 +1717,28 @@ BOOL CtrlHandler(DWORD fdwCtrlType)
1657 1717 {
1658 1718 // Handle the CTRL+C signal.
1659 1719 case CTRL_C_EVENT:
1660   - Beep(1000, 1);
1661   - OutputProfiling();
1662   - // Debugger::DumpProcesses();
1663   - // my_exit(1);
  1720 +fprintf(stderr, "CTRL+C received\n");
  1721 +fflush(stderr);
1664 1722 quitingVM = true;
  1723 + Beep(1000, 1);
  1724 + OutputProfiling();
  1725 + // Debugger::DumpProcesses();
  1726 + // my_exit(1);
  1727 +
1665 1728 return TRUE;
1666 1729  
1667 1730 // CTRL+CLOSE: confirm that the user wants to exit.
1668 1731 case CTRL_CLOSE_EVENT:
1669   - // OutputProfiling();
1670   - // my_exit(1);
1671 1732 quitingVM = true;
  1733 + // OutputProfiling();
  1734 + // my_exit(1);
  1735 +
1672 1736 return TRUE;
1673 1737  
1674 1738 case CTRL_BREAK_EVENT:
1675   - //OutputProfiling();
1676 1739 quitingVM = true;
  1740 + //OutputProfiling();
  1741 +
1677 1742 return TRUE;
1678 1743  
1679 1744 // Pass other signals to the next handler.
... ... @@ -1720,12 +1785,12 @@ int main(int argc, char **argv)
1720 1785 unsigned integer 0. */
1721 1786 U32 args = 0;
1722 1787  
1723   - /* signal are only managed under Linux/POSIX environement */
1724   -#if defined(_LINUX_) || defined(__BEOS__)
  1788 + /* signal are only managed under Linux/POSIX environement */
  1789 +#if defined(_LINUX_) || defined(__BEOS__)
1725 1790 // declare sigaction struct for ignoring a signal (here SIGPIPE, which made ssl_write connection broken)
1726 1791 struct sigaction sa;
1727 1792 #endif
1728   -
  1793 +
1729 1794 initftime();
1730 1795  
1731 1796 #ifdef debug_vm
... ... @@ -1764,9 +1829,9 @@ int main(int argc, char **argv)
1764 1829 for (i = 0; i < 5; i++) ((U8 *)anubis_empty_string)[i] = 0;
1765 1830 for (i = 0; i < 8; i++) ((U8 *)anubis_empty_byte_array)[i] = 0;
1766 1831  
1767   - /* signal are only managed under Linux/POSIX environement */
  1832 + /* signal are only managed under Linux/POSIX environement */
1768 1833 #if defined(_LINUX_) || defined(__BEOS__)
1769   - sa.sa_handler = SIG_IGN; //
  1834 + sa.sa_handler = SIG_IGN; //
1770 1835 sa.sa_flags = 0;
1771 1836 sigemptyset(&sa.sa_mask);
1772 1837  
... ...
anubis_dev/vm/src/bsd_socket.h
... ... @@ -24,59 +24,59 @@
24 24 #include "AnubisSupport.h"
25 25  
26 26 #define af_packet 0
27   -#define af_inet 1
28   -#define af_inet6 2
  27 +#define af_inet 1
  28 +#define af_inet6 2
29 29  
30 30 inline int GetSocketDomain(int anubis_alternative)
31 31 {
32   - switch(anubis_alternative)
33   - {
  32 + switch(anubis_alternative)
  33 + {
34 34 #ifdef LINUX
35   - case af_packet:
36   - return AF_PACKET;
37   -#endif
38   - case af_inet:
39   - return AF_INET;
40   - case af_inet6:
41   - return AF_INET6;
42   - default:
43   - assert(0);
44   - return AF_UNSPEC;
45   - }
  35 + case af_packet:
  36 + return AF_PACKET;
  37 +#endif
  38 + case af_inet:
  39 + return AF_INET;
  40 + case af_inet6:
  41 + return AF_INET6;
  42 + default:
  43 + assert(0);
  44 + return AF_UNSPEC;
  45 + }
46 46 }
47 47  
48   -#define sock_raw 0
49   -#define sock_dgram 1
  48 +#define sock_raw 0
  49 +#define sock_dgram 1
50 50 #define sock_stream 2
51 51  
52 52 inline int GetSocketType(int anubis_alternative)
53 53 {
54   - switch(anubis_alternative)
55   - {
56   - case sock_raw:
57   - return sock_raw;
58   - case sock_dgram:
59   - return SOCK_DGRAM;
60   - case sock_stream:
61   - return SOCK_STREAM;
62   - default:
63   - assert(0);
64   - return 0;
65   - }
  54 + switch(anubis_alternative)
  55 + {
  56 + case sock_raw:
  57 + return sock_raw;
  58 + case sock_dgram:
  59 + return SOCK_DGRAM;
  60 + case sock_stream:
  61 + return SOCK_STREAM;
  62 + default:
  63 + assert(0);
  64 + return 0;
  65 + }
66 66 }
67 67  
68 68  
69 69 enum {
70   - so_broadcast,
71   - so_debug,
72   - so_dontroute,
73   - so_keepaline,
74   - so_linger,
75   - so_rcvbuf,
76   - so_sndbuf,
77   - so_reuseaddr,
78   - // TCP level
79   - tcp_nodelay,
  70 + so_broadcast,
  71 + so_debug,
  72 + so_dontroute,
  73 + so_keepaline,
  74 + so_linger,
  75 + so_rcvbuf,
  76 + so_sndbuf,
  77 + so_reuseaddr,
  78 + // TCP level
  79 + tcp_nodelay,
80 80 };
81 81  
82 82  
... ... @@ -86,54 +86,54 @@ enum {
86 86 #define sockopt_error_bad_optlen (2)
87 87 #define sockopt_error_unknown_option (3)
88 88 #define sockopt_error_not_a_socket (4)
89   -#define sockopt_error_unknown (5)
  89 +#define sockopt_error_unknown (5)
90 90  
91 91 U8 Sockopt_Error2Alternative(int err)
92 92 {
93   - switch(err)
94   - {
95   - case EBADF:
96   - return sockopt_error_bad_socket;
97   - case EFAULT:
98   - return sockopt_error_bad_address;
99   - case EINVAL:
100   - return sockopt_error_bad_optlen;
101   - case ENOPROTOOPT:
102   - return sockopt_error_unknown_option;
103   - case ENOTSOCK:
104   - return sockopt_error_not_a_socket;
105   - default:
106   - return sockopt_error_unknown;
107   - }
  93 + switch(err)
  94 + {
  95 + case EBADF:
  96 + return sockopt_error_bad_socket;
  97 + case EFAULT:
  98 + return sockopt_error_bad_address;
  99 + case EINVAL:
  100 + return sockopt_error_bad_optlen;
  101 + case ENOPROTOOPT:
  102 + return sockopt_error_unknown_option;
  103 + case ENOTSOCK:
  104 + return sockopt_error_not_a_socket;
  105 + default:
  106 + return sockopt_error_unknown;
  107 + }
108 108 }
109 109  
110 110  
111 111 // BindError:
112 112 enum {
113   - no_permission, // EACCES The address is protected, and the user is not the superuser.
114   - addr_in_use, // EADDRINUSE The given address is already in use.
115   - bad_socket, // EBADF sockfd is not a valid descriptor.
116   - already_bound, // EINVAL The socket is already bound to an address.
117   - not_a_socket, // ENOTSOCK sockfd is a descriptor for a file, not a socket.
  113 + no_permission, // EACCES The address is protected, and the user is not the superuser.
  114 + addr_in_use, // EADDRINUSE The given address is already in use.
  115 + bad_socket, // EBADF sockfd is not a valid descriptor.
  116 + already_bound, // EINVAL The socket is already bound to an address.
  117 + not_a_socket, // ENOTSOCK sockfd is a descriptor for a file, not a socket.
118 118 };
119 119  
120 120  
121 121 U8 Bind_Error2Alternative(int err)
122 122 {
123   - switch(err)
124   - {
125   - case EACCES:
126   - return no_permission;
127   - case EADDRINUSE:
128   - return addr_in_use;
129   - case EBADF:
130   - return bad_socket;
131   - case EINVAL:
132   - return already_bound;
133   - case ENOTSOCK:
134   - return not_a_socket;
135   - }
136   - return no_permission;
  123 + switch(err)
  124 + {
  125 + case EACCES:
  126 + return no_permission;
  127 + case EADDRINUSE:
  128 + return addr_in_use;
  129 + case EBADF:
  130 + return bad_socket;
  131 + case EINVAL:
  132 + return already_bound;
  133 + case ENOTSOCK:
  134 + return not_a_socket;
  135 + }
  136 + return no_permission;
137 137 };
138 138  
139 139  
... ... @@ -142,12 +142,12 @@ U8 Bind_Error2Alternative(int err)
142 142  
143 143 int RecvFrom_Flags(U8 anubisFlags)
144 144 {
145   - int flags = 0;
146   - if (anubisFlags & recv_flag_msg_peek)
147   - flags |= MSG_PEEK;
148   - if (anubisFlags & recv_flag_msg_out_of_band)
149   - flags |= MSG_OOB;
150   - return flags;
  145 + int flags = 0;
  146 + if (anubisFlags & recv_flag_msg_peek)
  147 + flags |= MSG_PEEK;
  148 + if (anubisFlags & recv_flag_msg_out_of_band)
  149 + flags |= MSG_OOB;
  150 + return flags;
151 151 }
152 152  
153 153  
... ... @@ -164,29 +164,29 @@ int RecvFrom_Flags(U8 anubisFlags)
164 164  
165 165 U8 Recv_Error2Alternative(int err)
166 166 {
167   - switch(err)
168   - {
169   - case EAGAIN:
  167 + switch(err)
  168 + {
  169 + case EAGAIN:
170 170 #if EAGAIN != EWOULDBLOCK
171   - case EWOULDBLOCK:
  171 + case EWOULDBLOCK:
172 172 #endif
173   - return recv_error_no_data;
174   - case EBADF:
175   - return recv_error_bad_socket;
176   - case ECONNREFUSED:
177   - return recv_error_connection_refused;
178   - case EINTR:
179   - return recv_error_interrupted;
180   - case EINVAL:
181   - return recv_error_invalid_argument;
182   - case ENOMEM:
183   - return recv_error_out_of_memory;
184   - case ENOTCONN:
185   - return recv_error_not_connected;
186   - case ENOTSOCK:
187   - return recv_error_not_a_socket;
188   - }
189   - return recv_error_other_error;
  173 + return recv_error_no_data;
  174 + case EBADF:
  175 + return recv_error_bad_socket;
  176 + case ECONNREFUSED:
  177 + return recv_error_connection_refused;
  178 + case EINTR:
  179 + return recv_error_interrupted;
  180 + case EINVAL:
  181 + return recv_error_invalid_argument;
  182 + case ENOMEM:
  183 + return recv_error_out_of_memory;
  184 + case ENOTCONN:
  185 + return recv_error_not_connected;
  186 + case ENOTSOCK:
  187 + return recv_error_not_a_socket;
  188 + }
  189 + return recv_error_other_error;
190 190 }
191 191  
192 192  
... ... @@ -197,20 +197,20 @@ U8 Recv_Error2Alternative(int err)
197 197  
198 198 int SendTo_Flags(U8 anubisFlags)
199 199 {
200   - int flags = 0;
201   - if (anubisFlags & send_flag_msg_dontroute)
202   - flags |= MSG_PEEK;
  200 + int flags = 0;
  201 + if (anubisFlags & send_flag_msg_dontroute)
  202 + flags |= MSG_PEEK;
203 203 #ifdef MSG_MORE
204   - if (anubisFlags & send_flag_msg_more)
205   - flags |= MSG_MORE;
  204 + if (anubisFlags & send_flag_msg_more)
  205 + flags |= MSG_MORE;
206 206 #endif
207 207 #ifdef MSG_NOSIGNAL
208   - if (anubisFlags & send_flag_msg_nosignal)
209   - flags |= MSG_NOSIGNAL;
  208 + if (anubisFlags & send_flag_msg_nosignal)
  209 + flags |= MSG_NOSIGNAL;
210 210 #endif
211   - if (anubisFlags & send_flag_msg_out_of_band)
212   - flags |= MSG_OOB;
213   - return flags;
  211 + if (anubisFlags & send_flag_msg_out_of_band)
  212 + flags |= MSG_OOB;
  213 + return flags;
214 214 }
215 215  
216 216  
... ... @@ -229,47 +229,47 @@ int SendTo_Flags(U8 anubisFlags)
229 229 #define send_error_not_a_socket (12)
230 230 #define send_error_flag_not_supported (13)
231 231 #define send_error_localy_closed (14)
232   -#define send_error_other_error (15)
  232 +#define send_error_other_error (15)
233 233  
234 234 U8 Send_Error2Alternative(int err)
235 235 {
236   - switch(err)
237   - {
238   - case EACCES:
239   - return send_error_no_permission ;
240   - case EAGAIN:
  236 + switch(err)
  237 + {
  238 + case EACCES:
  239 + return send_error_no_permission ;
  240 + case EAGAIN:
241 241 #if EAGAIN != EWOULDBLOCK
242   - case EWOULDBLOCK:
  242 + case EWOULDBLOCK:
243 243 #endif
244   - return send_error_would_block ;
245   - case EBADF:
246   - return send_error_bad_socket ;
247   - case ECONNRESET:
248   - return send_error_connection_reset ;
249   - case EDESTADDRREQ:
250   - return send_error_dest_addr_required;
251   - case EINTR:
252   - return send_error_interrupted ;
253   - case EINVAL:
254   - return send_error_invalid_argument ;
255   - case EISCONN:
256   - return send_error_is_connected ;
257   - case EMSGSIZE:
258   - return send_error_msg_size ;
259   - case ENOBUFS:
260   - return send_error_queue_is_full ;
261   - case ENOMEM:
262   - return send_error_out_of_memory ;
263   - case ENOTCONN:
264   - return send_error_not_connected ;
265   - case ENOTSOCK:
266   - return send_error_not_a_socket ;
267   - case EOPNOTSUPP:
268   - return send_error_flag_not_supported;
269   - case EPIPE:
270   - return send_error_localy_closed ;
271   - }
272   - return send_error_other_error;
  244 + return send_error_would_block ;
  245 + case EBADF:
  246 + return send_error_bad_socket ;
  247 + case ECONNRESET:
  248 + return send_error_connection_reset ;
  249 + case EDESTADDRREQ:
  250 + return send_error_dest_addr_required;
  251 + case EINTR:
  252 + return send_error_interrupted ;
  253 + case EINVAL:
  254 + return send_error_invalid_argument ;
  255 + case EISCONN:
  256 + return send_error_is_connected ;
  257 + case EMSGSIZE:
  258 + return send_error_msg_size ;
  259 + case ENOBUFS:
  260 + return send_error_queue_is_full ;
  261 + case ENOMEM:
  262 + return send_error_out_of_memory ;
  263 + case ENOTCONN:
  264 + return send_error_not_connected ;
  265 + case ENOTSOCK:
  266 + return send_error_not_a_socket ;
  267 + case EOPNOTSUPP:
  268 + return send_error_flag_not_supported;
  269 + case EPIPE:
  270 + return send_error_localy_closed ;
  271 + }
  272 + return send_error_other_error;
273 273 }
274 274  
275   -#endif //ndef __BSD_SOCKET_H__
  275 +#endif //ndef __BSD_SOCKET_H__
... ...
anubis_dev/vm/src/syscall.cpp
... ... @@ -91,6 +91,7 @@ extern &quot;C&quot; {
91 91 #include "AnubisFileLocker.h"
92 92 #include "bsd_socket.h"
93 93 #include "dbapi_tools.h"
  94 +#include "vm_socket.h"
94 95  
95 96 USING_NAMESPACE(CM);
96 97  
... ... @@ -288,11 +289,10 @@ struct DbConnectContext {
288 289 char *username;
289 290 char *password;
290 291 SAClient_t dbType;
291   -
292 292 SAConnection *dbcnx; // db connection
293 293 U32 second_seg; // Saving the segment allocated for the result
294 294  
295   - int wakeup_pipe[2]; // pipe for waking up the wait_for_event when the thread has finish
  295 + int wakeup_socket[2]; //socket for waking up the wait_for_event when the thread has finish
296 296  
297 297 std::atomic<bool> is_finished;
298 298 std::atomic<bool> has_error;
... ... @@ -300,32 +300,276 @@ struct DbConnectContext {
300 300 char *err_text;
301 301 };
302 302  
  303 +/*
  304 + * Notify the VM that the asynchronous thread has finished.
  305 + */
  306 +static int db_wakeup(int fd)
  307 +{
  308 + char c = 1;
  309 +
  310 +#ifdef WIN32
  311 + return send((SOCKET)fd, &c, 1, 0);
  312 +#else
  313 + return (int)send(fd, &c, 1, 0);
  314 +#endif
  315 +}
  316 +
  317 +
  318 +
303 319 // Performing the connection outside the VM's main thread
304   -static void db_connect_thread(DbConnectContext *ctx) {
305   - char c = 1; //for writing into pipe
306   - ctx->dbcnx = new SAConnection();
307   - try {
308   - ctx->dbcnx->Connect(ctx->db_string, ctx->username, ctx->password, ctx->dbType);
309   - ctx->has_error = false;
310   - } catch(SAException &ex) {
311   - ctx->has_error = true;
312   - ctx->err_code = ex.ErrNativeCode();
313   - // Immediate duplication to prevent loss upon the destruction of the exception.
314   - ctx->err_text = strdup((const char*)ex.ErrText());
315   - LOGERROR("[VM DB] [Thread] Connection failed. Native error code : %d '%s'\n", ctx->err_code, ctx->err_text);
316   - }
317   - ctx->is_finished = true;
318   - write(ctx->wakeup_pipe[1], &c, 1);
  320 +static void db_connect_thread(DbConnectContext *ctx)
  321 +{
  322 +
  323 + ctx->dbcnx = new SAConnection();
  324 +
  325 + try {
  326 + ctx->dbcnx->Connect(ctx->db_string, ctx->username, ctx->password, ctx->dbType);
  327 + ctx->has_error = false;
  328 +
  329 + }
  330 + catch(SAException &ex)
  331 + {
  332 + ctx->has_error = true;
  333 + ctx->err_code = ex.ErrNativeCode();
  334 + // Immediate duplication to prevent loss upon the destruction of the exception.
  335 + ctx->err_text = strdup((const char*)ex.ErrText());
  336 + LOGERROR("[VM DB] [Thread] Connection failed. Native error code : %d '%s'\n", ctx->err_code, ctx->err_text);
  337 + }
  338 +
  339 + /*
  340 + * The result is now completely prepared.
  341 + * Publish completion before waking up the VM.
  342 + */
  343 + ctx->is_finished = true;
  344 +
  345 + /*
  346 + * Notify the scheduler through the socket.
  347 + */
  348 + if (db_wakeup(ctx->wakeup_socket[1]) != 1)
  349 + {
  350 + LOGERROR("[VM DB] [Thread] Unable to wake up VM with socket\n");
  351 + }
  352 +
319 353 }
320 354  
321   -static bool is_fd_valid(int fd)
  355 +
  356 +
  357 +/*
  358 + * Consume the wakeup notification.
  359 + */
  360 +static int db_consume_wakeup(int fd)
322 361 {
323   - errno = 0;
  362 + char buffer[32];
  363 +
  364 +#ifdef WIN32
  365 +
  366 + int r = recv(
  367 + (SOCKET)fd,
  368 + buffer,
  369 + sizeof(buffer),
  370 + 0);
  371 +
  372 + return r;
  373 +
  374 +#else
  375 + return (int)recv(fd, buffer, sizeof(buffer), 0);
  376 +#endif
  377 +}
  378 +
  379 +/*
  380 + * Close a wakeup socket.
  381 + */
  382 +static void db_close_wakeup_socket(int fd)
  383 +{
  384 +#ifdef WIN32
  385 + if (fd >= 0)
  386 + closesocket((SOCKET)fd);
  387 +#else
  388 + if (fd >= 0)
  389 + close(fd);
  390 +#endif
  391 +}
  392 +
  393 +/*
  394 + * Create a pair of connected TCP sockets on the local host.
  395 + *
  396 + * socket[0] is used by the VM and registered in the event mechanism.
  397 + * socket[1] is used by the asynchronous thread to notify the VM.
  398 + *
  399 + * The same technology is used on Linux and Windows.
  400 + */
  401 +static int create_db_wakeup_socket_pair(int sockets[2])
  402 +{
  403 + int listener = -1;
  404 + int client = -1;
  405 + int server = -1;
  406 +
  407 + struct sockaddr_in address;
  408 +
  409 +#ifdef WIN32
  410 + int address_length;
  411 +#else
  412 + socklen_t address_length;
  413 +#endif
  414 +
  415 + memset(&address, 0, sizeof(address));
  416 +
  417 + address.sin_family = AF_INET;
  418 + address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  419 + address.sin_port = htons(0);
  420 +
  421 + /* Create the local listening socket */
  422 +#ifdef WIN32
  423 + SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  424 +
  425 + if (s == INVALID_SOCKET)
  426 + {
  427 + LOGERROR("[VM DB] Unable to create wakeup listening socket WSA=%d\n",WSAGetLastError());
  428 + fflush(stderr);
  429 + goto error;
  430 + }
  431 +
  432 + listener = (int)s;
  433 +
  434 +#else
  435 + listener = socket(AF_INET, SOCK_STREAM, 0);
  436 +
  437 + if (listener < 0)
  438 + {
  439 + LOGERROR("[VM DB] Unable to create wakeup listening socket\n");
  440 + goto error;
  441 + }
  442 +#endif
  443 +
  444 +
  445 + /* Bind on localhost and let the system choose the port */
  446 + if (bind(listener, (struct sockaddr *)&address, sizeof(address)) < 0)
  447 + {
  448 + goto error;
  449 + }
  450 +
  451 + // Listen
  452 + if (listen(listener, 1) < 0)
  453 + {
  454 + goto error;
  455 + }
  456 + /* Get the port selected by the system */
  457 + address_length = sizeof(address);
  458 +
  459 + if (getsockname(
  460 + listener,
  461 + (struct sockaddr *)&address,
  462 + &address_length) < 0)
  463 + {
  464 + goto error;
  465 + }
  466 +
  467 + /* Create the client socket */
  468 +#ifdef WIN32
  469 + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  470 +
  471 + if (s == INVALID_SOCKET)
  472 + {
  473 + goto error;
  474 + }
  475 +
  476 + client = (int)s;
  477 +#else
  478 + client = socket(AF_INET, SOCK_STREAM, 0);
  479 +
  480 + if (client < 0)
  481 + {
  482 + goto error;
  483 + }
  484 +#endif
  485 +
  486 + /* Connect the client to the local listening socket */
  487 + if (connect(
  488 + client,
  489 + (struct sockaddr *)&address,
  490 + address_length) < 0)
  491 + {
  492 + goto error;
  493 + }
  494 +
  495 + /* Accept the connection */
  496 +#ifdef WIN32
  497 + s = accept((SOCKET)listener, NULL, NULL);
  498 +
  499 + if (s == INVALID_SOCKET)
  500 + {
  501 + goto error;
  502 + }
  503 + server = (int)s;
  504 +#else
  505 + server = accept(listener, NULL, NULL);
  506 +
  507 + if (server < 0)
  508 + {
  509 + goto error;
  510 + }
  511 +#endif
  512 +
  513 + /* The listening socket is no longer needed */
  514 +#ifdef WIN32
  515 + closesocket((SOCKET)listener);
  516 +#else
  517 + close(listener);
  518 +#endif
  519 +
  520 + sockets[0] = server;
  521 + sockets[1] = client;
  522 +
  523 + return 0;
  524 +
  525 +
  526 +error:
  527 + fprintf(stderr,
  528 + "[VM DB] create_db_wakeup_socket_pair FAILED\n");
  529 + fflush(stderr);
  530 +
  531 +#ifdef WIN32
  532 + if (listener >= 0)
  533 + closesocket((SOCKET)listener);
  534 +
  535 + if (client >= 0)
  536 + closesocket((SOCKET)client);
324 537  
325   - if (fcntl(fd, F_GETFL) == -1)
326   - return errno != EBADF;
  538 + if (server >= 0)
  539 + closesocket((SOCKET)server);
  540 +#else
  541 + if (listener >= 0)
  542 + close(listener);
  543 +
  544 + if (client >= 0)
  545 + close(client);
  546 +
  547 + if (server >= 0)
  548 + close(server);
  549 +#endif
327 550  
328   - return true;
  551 + sockets[0] = -1;
  552 + sockets[1] = -1;
  553 +
  554 + return -1;
  555 +}
  556 +
  557 +static bool is_fd_valid(int fd)
  558 +{
  559 +#if defined(_WIN32) || defined(__MINGW32__)
  560 + int socket_type = 0;
  561 + int socket_type_len = sizeof(socket_type);
  562 +
  563 + return getsockopt(
  564 + (SOCKET)fd,
  565 + SOL_SOCKET,
  566 + SO_TYPE,
  567 + (char *)&socket_type,
  568 + &socket_type_len) == 0;
  569 +#else
  570 + // fcntl standard for POSIX (Linux, macOS, MSYS-native) environment
  571 + return fcntl(fd, F_GETFD) != -1;
  572 +#endif
329 573 }
330 574  
331 575 // code factorization for all SQLite3 instruction returning a SQLite3Result
... ... @@ -5594,7 +5838,8 @@ returns: Maybe(#StructPtr(X509)) */
5594 5838  
5595 5839 /* We have not read the maximal number of
5596 5840 bytes. We try to read more bytes (but not too many). */
5597   -
  5841 + ERR_clear_error();
  5842 +
5598 5843 r = SSL_read( ssl,
5599 5844 (char *)MAM(m_DUC2), // where to write the bytes
5600 5845 max_bytes - MAM(m_DUC3) // the maximum to read (max bytes - already read bytes)
... ... @@ -5670,21 +5915,21 @@ returns: Maybe(#StructPtr(X509)) */
5670 5915 case SSL_ERROR_ZERO_RETURN:
5671 5916 case SSL_ERROR_SYSCALL:
5672 5917 {
5673   - int err = errno;
  5918 + int err = LAST_SOCKET_ERROR;
5674 5919 unsigned long ssl_err = ERR_get_error();
  5920 +
5675 5921  
5676   - LOGINFO("ssl_byte_array_read: SSL_ERROR_SYSCALL r=%d errno=%d (%s) ERR=%lu\n", r, err, strerror(err), ssl_err);
5677   -
5678   - /* r == 0 + errno == 0 + no OpenSSL error :
5679   - * closed connection / EOF.
5680   - */
5681 5922 if (r == 0 && err == 0 && ssl_err == 0)
5682 5923 {
5683   - LOGINFO("ssl_byte_array_read: EOF on fd=%d\n", tcp_handle);
5684   -
5685   - // IMPORTANT :
5686   - //Make sure not to put the process back into the waiting_for_event state.
5687   -
  5924 + /*
  5925 + * SSL_read() returned 0 and there is no socket error and no OpenSSL error.
  5926 + *
  5927 + * This is simply an EOF: the peer closed the connection.
  5928 + * This is a normal event, especially with HTTP clients.
  5929 + *
  5930 + * IMPORTANT :
  5931 + * Make sure not to put the process back into the waiting_for_event state.
  5932 + */
5688 5933 MAM(m_allocator)->FreeDataSegment((U32 *)(((U32 *)MAM(m_DUC1))[1]));
5689 5934 MAM(m_allocator)->FreeDataSegment((U32 *)MAM(m_DUC1));
5690 5935 MAM(m_R) = 0; /* failure */
... ... @@ -5692,6 +5937,12 @@ returns: Maybe(#StructPtr(X509)) */
5692 5937 MAM(m_IP) += 1+2;
5693 5938 return;
5694 5939 }
  5940 +
  5941 + // There is an actual socket error or an OpenSSL error.
  5942 + if (err != ECONNABORTED && err != ECONNRESET)
  5943 + {
  5944 + LOGINFO("ssl_byte_array_read: SSL_ERROR_SYSCALL r=%d errno=%d (%s) ERR=%lu\n", r, err, strerror(err), ssl_err);
  5945 + }
5695 5946  
5696 5947 if (ssl_err != 0)
5697 5948 {
... ... @@ -5701,7 +5952,7 @@ returns: Maybe(#StructPtr(X509)) */
5701 5952 MAM(m_allocator)->FreeDataSegment((U32 *)(((U32 *)MAM(m_DUC1))[1]));
5702 5953 MAM(m_allocator)->FreeDataSegment((U32 *)MAM(m_DUC1));
5703 5954  
5704   - MAM(m_R) = 0;
  5955 + MAM(m_R) = 0; /* failure */
5705 5956 MAM(m_duc_non_empty) = 0;
5706 5957 MAM(m_IP) += 1+2;
5707 5958 return;
... ... @@ -5780,6 +6031,7 @@ returns: Maybe(#StructPtr(X509)) */
5780 6031 {
5781 6032 U32 ssl_conn = *(MAM(m_SP)-1);
5782 6033 SSL *ssl;
  6034 + int tcp_handle;
5783 6035 U8 *text;
5784 6036 int size;
5785 6037 int write_result, ssl_err;
... ... @@ -5813,9 +6065,9 @@ returns: Maybe(#StructPtr(X509)) */
5813 6065 }
5814 6066  
5815 6067 ssl = (SSL *)(((U32 *)(((U32 *)ssl_conn)[1]))[1]);
5816   - write_result = SSL_write(ssl,
5817   - (char *)text+MAM(m_DUC2),
5818   - size-MAM(m_DUC2));
  6068 + tcp_handle = *((int *)(((U8 *)(((U32 *)ssl_conn)[2]))+8));
  6069 +
  6070 + write_result = SSL_write(ssl, (char *)text+MAM(m_DUC2), size-MAM(m_DUC2));
5819 6071  
5820 6072  
5821 6073 //printf("ssl_write_byte_array: SSL_write returned %d\n",write_result); fflush(stdout);
... ... @@ -5840,26 +6092,43 @@ returns: Maybe(#StructPtr(X509)) */
5840 6092 }
5841 6093  
5842 6094 case SSL_ERROR_WANT_READ:
  6095 + {
  6096 + MAM(RegisterFDIn)(tcp_handle);
  6097 + MAM(m_steps) = 0;
  6098 + return;
  6099 + }
  6100 +
5843 6101 case SSL_ERROR_WANT_WRITE:
5844   - { // wait
5845   - //printf("ssl_write_byte_array: waiting; error code = %d\n",ssl_err); fflush(stdout);
5846   - MAM(m_steps) = 0;
  6102 + {
  6103 + MAM(RegisterFDOut)(tcp_handle);
  6104 + MAM(m_steps) = 0;
5847 6105 return;
5848 6106 }
5849 6107  
  6108 + case SSL_ERROR_SYSCALL:
  6109 + {
  6110 + MAM(m_allocator)->FreeDataSegment((U32 *)MAM(m_R));
  6111 + MAM(m_duc_non_empty) = 0;
  6112 + MAM(m_R) = 0; /* failure */
  6113 + MAM(m_IP) += 1+2;
  6114 + return;
  6115 + }
  6116 +
5850 6117 default:
5851 6118 {
5852 6119 unsigned long err_code = ERR_get_error();
5853 6120 #if OPENSSL_VERSION_NUMBER < 0x30000000L
5854 6121 SSL_load_error_strings();
5855   - LOGERROR("SSL_ERROR default %d ERR_get_error %ld LIB %s Function %s Reason %s\n", ssl_err, err_code,
5856   - ERR_lib_error_string(err_code),
5857   - ERR_func_error_string(err_code),
5858   - ERR_reason_error_string(err_code));
  6122 + LOGERROR("SSL_ERROR default %d ERR_get_error %ld LIB %s Function %s Reason %s\n",
  6123 + ssl_err, err_code,
  6124 + ERR_lib_error_string(err_code),
  6125 + ERR_func_error_string(err_code),
  6126 + ERR_reason_error_string(err_code));
5859 6127 #else
5860   - LOGERROR("SSL_ERROR default %d ERR_get_error %ld LIB %s Reason %s\n", ssl_err, err_code,
5861   - ERR_lib_error_string(err_code),
5862   - ERR_reason_error_string(err_code));
  6128 + LOGERROR("SSL_ERROR default %d ERR_get_error %ld LIB %s Reason %s\n",
  6129 + ssl_err, err_code,
  6130 + ERR_lib_error_string(err_code),
  6131 + ERR_reason_error_string(err_code));
5863 6132 #endif
5864 6133  
5865 6134 LOGERROR("ssl_write_byte_array: ssl error code = %d \n",ssl_err);
... ... @@ -7114,7 +7383,6 @@ where ptr is a pointer to the connection data segment.
7114 7383 syscall_case(open_tcp_ip_connection)
7115 7384 {
7116 7385 int i;
7117   -LOGINFO("[TCP CONNECT] PID=%u IP=%u entering open_tcp_ip_connection\n", MAM(GetPid()), relative_IP(MAM(m_IP)));
7118 7386  
7119 7387 if (!MAM(m_duc_non_empty))
7120 7388 {
... ... @@ -7153,10 +7421,8 @@ LOGINFO(&quot;[TCP CONNECT] PID=%u IP=%u entering open_tcp_ip_connection\n&quot;, MAM(GetP
7153 7421 /* the socket handle has been put in the connection segment */
7154 7422 MAM(m_duc_non_empty) = 1;
7155 7423 }
7156   -LOGINFO("[TCP CONNECT] PID=%u fd=%u after open_IP_connection\n", MAM(GetPid()), ((U32 *)MAM(m_DUC2))[2]);
7157 7424 /* check if connection ready */
7158 7425 i = is_IP_connection_ready(MAM(m_DUC2));
7159   -LOGINFO("[TCP CONNECT] PID=%u is_IP_connection_ready=%d fd=%u\n",MAM(GetPid()), i, ((U32 *)MAM(m_DUC2))[2]);
7160 7426 if (i == 0) /* connection ready */
7161 7427 {
7162 7428 *(((U32 *)(MAM(m_DUC1)))+1) = MAM(m_DUC2);
... ... @@ -7622,20 +7888,14 @@ Returns: UDP_Send_Result:
7622 7888 memcpy(&sa.sin_addr,(U8 *)&addr,sizeof(U32));
7623 7889 sa.sin_port = htons((unsigned short)port);
7624 7890  
7625   -#ifdef WIN32
7626   - if (sendto(sock,(const char *)data,(size_t)data_length,0,
7627   - (struct sockaddr *)&sa,sizeof(struct sockaddr_in)) <0)
7628   -#else
7629   - if (sendto(sock,(void *)data,(size_t)data_length,0,
7630   - (struct sockaddr *)&sa,sizeof(struct sockaddr_in)) <0)
7631   -#endif
7632   - {
7633   - MAM(m_R) = 0; /* network_unreachable */
7634   - }
7635   - else
7636   - {
7637   - MAM(m_R) = 1; /* packet_sent */
7638   - }
  7891 + if (vm_socket_sendto(sock, data, data_length, 0, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in)) <0)
  7892 + {
  7893 + MAM(m_R) = 0; /* network_unreachable */
  7894 + }
  7895 + else
  7896 + {
  7897 + MAM(m_R) = 1; /* packet_sent */
  7898 + }
7639 7899 }
7640 7900 MAM(m_IP) += 1+2;
7641 7901 return;
... ... @@ -7731,12 +7991,14 @@ n (U32) = number of bytes of data
7731 7991 /* We allow receiving 1 byte more than the maximum. If we get that byte,
7732 7992 this means that the data received must be truncated. */
7733 7993 #ifdef WIN32
  7994 +
7734 7995 if ((nbytes = recvfrom(sock,
7735 7996 (char *)(((U8 *)(((U32*)MAM(m_DUC1))[1]))+8),
7736 7997 (size_t)(max_packet_size+1),
7737 7998 0,
7738 7999 (struct sockaddr *)&sa,
7739 8000 &socklen)) < 0)
  8001 +
7740 8002 #else
7741 8003 if ((nbytes = recvfrom(sock,
7742 8004 (void *)(((U8 *)(((U32*)MAM(m_DUC1))[1]))+8),
... ... @@ -7746,11 +8008,7 @@ n (U32) = number of bytes of data
7746 8008 &socklen)) < 0)
7747 8009 #endif
7748 8010 {
7749   -#ifdef WIN32
7750   - errcode = GetLastError();
7751   -#else
7752   - errcode = errno;
7753   -#endif
  8011 + errcode = LAST_SOCKET_ERROR;
7754 8012  
7755 8013 switch(errcode)
7756 8014 {
... ... @@ -13983,47 +14241,99 @@ syscall_case(db_connect)
13983 14241 {
13984 14242 // --- THREAD WAITING STATE ---
13985 14243 DbConnectContext *ctx = (DbConnectContext *)MAM(m_DUC1);
13986   -
13987   - if (!ctx->is_finished) // Thread still running;
  14244 + bool thread_finished = ctx->is_finished;
  14245 + bool thread_has_error = ctx->has_error;
  14246 +
  14247 + if (!thread_finished) // Thread still running;
13988 14248 {
13989   - //LOGINFO("[VM DB] [Syscall] Thread still running.\n");
13990   - MAM(RegisterFDIn)(ctx->wakeup_pipe[0]);
  14249 + //LOGINFO("[VM DB] [Syscall] Thread still running.\n");
  14250 + /*
  14251 + * The process was woken up by an event, but the DB thread
  14252 + * has not yet finished.
  14253 + *
  14254 + * RegisterFDIn() adds the FD to the process and global list
  14255 + * and puts the process back into waiting_for_event.
  14256 + */
  14257 + MAM(RegisterFDIn)(ctx->wakeup_socket[0]);
13991 14258 MAM(m_steps) = 0; // force VM reordering.
13992 14259 return;
13993 14260 }
13994   -
  14261 +
13995 14262 // The thread has finished executing.
13996   - //LOGINFO("[VM DB] [Syscall] Thread return detected by the VM\n");
13997   -
13998   - if (!ctx->has_error)
  14263 + // The wakeup event has been consumed.
  14264 + db_consume_wakeup(ctx->wakeup_socket[0]);
  14265 +
  14266 + //The DB connection is no longer waiting for an event.
  14267 + MAM(UnregisterFDIn)(ctx->wakeup_socket[0]);
  14268 +
  14269 + // The sockets are no longer needed.
  14270 + db_close_wakeup_socket(ctx->wakeup_socket[0]);
  14271 + db_close_wakeup_socket(ctx->wakeup_socket[1]);
  14272 +
  14273 + if (!thread_has_error)
13999 14274 {
14000 14275 // successfuly connected
14001 14276 ((U32 *)(ctx->second_seg))[1] = (U32)(ctx->dbcnx);
14002 14277 ((U32 *)(MAM(m_R)))[1] = ctx->second_seg;
  14278 + // Transfer ownership of the SAConnection to the Anubis result.
  14279 + ctx->dbcnx = NULL;
14003 14280 MAM(m_R) |= 1; // Select 'ok' alternative
14004   -
  14281 +
14005 14282 MAM(m_duc_non_empty) = 0;
14006 14283 //LOGINFO("[VM DB] [Syscall] Finalized return structure (success)\n");
14007 14284 }
14008 14285 else
14009 14286 {
14010   - // Connection failure: release the segment.
  14287 + /* The asynchronous DB connection has failed.
  14288 + * From this point onward, the DbConnectContext is no longer needed. The error
  14289 + * information is transferred to the DUC registers so that MakeDbError() can be
  14290 + * retried if the VM runs out of memory.
  14291 + */
14011 14292 LOGERROR("[VM DB] [Syscall] Handling the error returned by the thread\n");
  14293 +
  14294 + /* The result segment was allocated before starting the thread.
  14295 + * It is no longer needed because the DB connection failed.
  14296 + */
14012 14297 MAM(m_allocator)->FreeDataSegment((U32 *)ctx->second_seg);
14013 14298  
14014   - // Configuration of DUC registers to simulate the original memory starvation state.
  14299 + /* Transfer the error information from the asynchronous context to the DUC registers.
  14300 + * DUC3 becomes the owner of err_text.
  14301 + */
14015 14302 MAM(m_DUC1) = MAM(m_R);
14016 14303 MAM(m_DUC2) = ctx->err_code;
14017 14304 MAM(m_DUC3) = (U32)ctx->err_text; // Already allocated via strdup in the thread
14018 14305  
14019   -/* free(ctx->db_string);
14020   - free(ctx->username);
14021   - free(ctx->password);
14022   - delete ctx;*/
14023   -
  14306 + /*
  14307 + * The context itself cannot be deleted before MakeDbError()
  14308 + * has completed because ctx->err_text is currently owned
  14309 + * through MAM(m_DUC3).
  14310 + */
  14311 + /*
  14312 + * Ownership of err_text has now been transferred to DUC3.
  14313 + * This is important because ctx is going to be destroyed now.
  14314 + */
  14315 + ctx->err_text = NULL;
  14316 + /*
  14317 + * The asynchronous operation is completely finished.
  14318 + * The context is no longer needed, even if MakeDbError()
  14319 + * subsequently fails because of memory exhaustion.
  14320 + */
  14321 +
14024 14322 // Immediate attempt to reproduce the error (identical to the original)
14025 14323 if(MakeDbError(MAM(m_DUC2), (const char*)MAM(m_DUC3), &second_seg, MAM(m_allocator)) == false)
14026 14324 {
  14325 + // Context cleanup
  14326 + free(ctx->db_string);
  14327 + free(ctx->username);
  14328 + free(ctx->password);
  14329 + if (ctx->dbcnx != NULL)
  14330 + {
  14331 + // Connect() failed, therefore the connection was not transferred to the Anubis result.
  14332 + delete ctx->dbcnx;
  14333 + ctx->dbcnx = NULL;
  14334 + }
  14335 + delete ctx;
  14336 +
14027 14337 LOGERROR("[VM DB] [Syscall] Memory exhaustion when the error occurred (MakeDbError). VM paused.\n");
14028 14338 MAM(m_status) = need_more_memory;
14029 14339 MAM(m_steps) = 0;
... ... @@ -14031,6 +14341,8 @@ syscall_case(db_connect)
14031 14341 }
14032 14342  
14033 14343 free((void*)MAM(m_DUC3));
  14344 + MAM(m_DUC3) = 0;
  14345 + //ctx->err_text = NULL;
14034 14346 MAM(m_R) = MAM(m_DUC1);
14035 14347 ((U32 *)(MAM(m_R)))[1] = second_seg;
14036 14348 MAM(m_duc_non_empty) = 0;
... ... @@ -14039,18 +14351,18 @@ syscall_case(db_connect)
14039 14351 }
14040 14352  
14041 14353 // Context cleanup
14042   - FD_CLR(ctx->wakeup_pipe[0], &descriptors_waited_for_input);
14043   - close(ctx->wakeup_pipe[0]);
14044   - close(ctx->wakeup_pipe[1]);
14045 14354 free(ctx->db_string);
14046 14355 free(ctx->username);
14047 14356 free(ctx->password);
  14357 + if (ctx->dbcnx != NULL)
  14358 + {
  14359 + delete ctx->dbcnx;
  14360 + ctx->dbcnx = NULL;
  14361 + }
14048 14362 delete ctx;
14049 14363 }
14050   - else
  14364 + else // --- out of memory condition (MakeDbError) ---
14051 14365 {
14052   - // --- out of memory condition (MakeDbError) ---
14053   - //LOGINFO("[VM DB] [Syscall] VM resumption following a memory starvation condition (MakeDbError)\n");
14054 14366 if(MakeDbError(MAM(m_DUC2), (const char*)MAM(m_DUC3), &second_seg, MAM(m_allocator)) == false)
14055 14367 {
14056 14368 //LOGERROR("[VM DB] [Syscall] Persistent out-of-memory condition. Pause maintained.\n");
... ... @@ -14062,7 +14374,6 @@ syscall_case(db_connect)
14062 14374 MAM(m_R) = MAM(m_DUC1);
14063 14375 ((U32 *)(MAM(m_R)))[1] = second_seg;
14064 14376 MAM(m_duc_non_empty) = 0;
14065   - //LOGINFO("[VM DB] [Syscall] Error finalized after memory recovery\n");
14066 14377 }
14067 14378 }
14068 14379 else
... ... @@ -14073,9 +14384,7 @@ syscall_case(db_connect)
14073 14384 char *password = ((char *)(*(MAM(m_SP)-3)))+4;
14074 14385 U32 client_type = *(MAM(m_SP)-4);
14075 14386 SAClient_t dbType = SA_Client_NotSpecified;
14076   -
14077   - //LOGINFO("[VM DB] [Syscall] Initializing db_connect (client_type: %u)\n", client_type);
14078   -
  14387 +
14079 14388 switch(client_type)
14080 14389 {
14081 14390 case 0: dbType = SA_Oracle_Client; break;
... ... @@ -14106,15 +14415,23 @@ syscall_case(db_connect)
14106 14415 ctx->err_code = 0;
14107 14416 ctx->err_text = NULL;
14108 14417 //creating the pipe which noticing the scheduler the asynchronous thread has finish his job
14109   - if(pipe(ctx->wakeup_pipe) < 0)
  14418 + if(create_db_wakeup_socket_pair(ctx->wakeup_socket) < 0)
14110 14419 {
14111   - LOGERROR("[VM DB] Unable to create wakeup pipe\n");
  14420 + LOGERROR("[VM DB] Unable to create wakeup socket pair\n");
14112 14421 MAM(m_status) = need_more_memory;
14113 14422 MAM(m_steps) = 0;
14114 14423 return;
14115 14424 }
14116   - FD_SET(ctx->wakeup_pipe[0], &descriptors_waited_for_input); //register pipe into global descriptors
14117   - MAM(m_fds_in).AddItemUnique((void *)ctx->wakeup_pipe[0]);
  14425 + /*
  14426 + * Register the socket into the event system.
  14427 + *
  14428 + * RegisterFDIn() also:
  14429 + * - adds the FD to the process input list
  14430 + * - adds the FD to descriptors_waited_for_input
  14431 + * - changes the process status to waiting_for_event
  14432 + */
  14433 + MAM(RegisterFDIn)(ctx->wakeup_socket[0]);
  14434 +
14118 14435 ctx->db_string = strdup(db_string);
14119 14436 ctx->username = strdup(username);
14120 14437 ctx->password = strdup(password);
... ... @@ -14126,17 +14443,13 @@ syscall_case(db_connect)
14126 14443 MAM(m_duc_non_empty) = 1;
14127 14444  
14128 14445 // Thread launch and detachment
14129   - //LOGINFO("[VM DB] [Syscall] Launch of the detached thread and switch of the VM to cooperative waiting state.\n");
14130 14446 std::thread t(db_connect_thread, ctx);
14131 14447 t.detach();
14132 14448  
14133   - MAM(m_status) = waiting_for_event; //waiting for the end of the thread by watching the pipe
14134   - //LOGINFO("[VM DB] [Syscall] waiting for event from thread.\n");
14135 14449 MAM(m_steps) = 0; /* forces immediate scheduling without incrementing the IP */
14136 14450 return;
14137 14451 }
14138 14452  
14139   - //LOGINFO("[VM DB] [Syscall] db_connect operation terminated, resume of bytecode execution\n");
14140 14453 MAM(m_IP) += 1+2;
14141 14454 MAM(m_steps) = 0; /* force scheduling after this call to the library */
14142 14455 return;
... ...
anubis_dev/vm/src/vm_launcher.cpp
... ... @@ -226,26 +226,49 @@ U32 launch_vm
226 226 //add Q in the end for SQLAPI. Because SQLAPI isn't an official flag we don't know if the
227 227 //vm has been compiled with it. So we try it at first
228 228 launch_try = vmversion + (is_flags?flags.Cstr():"_") + "Q" + extension;
229   -
  229 +
230 230 /* Remark the excevp function never return on success,
231 231 hence we will try different case until success or failure at the end of these tries */
232 232  
233 233 /* try to execute the vm -> "anbexec" + version + flags + Q (SQLAPI) */
234   - printf("try launch %s \n",launch_try.Cstr());
235   - execvp(launch_try.Cstr(), argv);
  234 + printf("try launch %s \n",launch_try.Cstr());
  235 +#ifdef WIN32
  236 +{
  237 + int result = (int)_spawnvp(_P_WAIT, launch_try.Cstr(), argv);
  238 + if (result != -1)
  239 + return result;
  240 +}
  241 +#else
  242 + execvp(launch_try.Cstr(), argv);
  243 +#endif
236 244  
237 245 /* try to execute the vm -> "anbexec" + version + flags */
238 246 if(is_flags)
239 247 {
240 248 launch_try = vmversion + flags + extension;
241   - printf("try launch %s \n",launch_try.Cstr());
242   - execvp(launch_try.Cstr(), argv);
  249 +#ifdef WIN32
  250 +{
  251 + int result = (int)_spawnvp(_P_WAIT, launch_try.Cstr(), argv);
  252 + if (result != -1)
  253 + return result;
  254 +}
  255 +#else
  256 + execvp(launch_try.Cstr(), argv);
  257 +#endif
243 258 }
244 259  
245 260 /* try to execute the vm -> "anbexec" + version */
246 261 launch_try = vmversion + extension;
247 262 printf("try launch %s \n",launch_try.Cstr());
248   - execvp(launch_try.Cstr(), argv);
  263 +#ifdef WIN32
  264 +{
  265 + int result = (int)_spawnvp(_P_WAIT, launch_try.Cstr(), argv);
  266 + if (result != -1)
  267 + return result;
  268 +}
  269 +#else
  270 + execvp(launch_try.Cstr(), argv);
  271 +#endif
249 272 printf("%s not found \n",launch_try.Cstr());
250 273 my_exit(0);
251 274 return 0;
... ...
anubis_dev/vm/src/vm_socket.cpp 0 → 100644
  1 +
  2 +#include <stdio.h>
  3 +#include "vm_socket.h"
  4 +
  5 +int vm_socket_select(
  6 + int nfds,
  7 + fd_set *readfds,
  8 + fd_set *writefds,
  9 + fd_set *exceptfds,
  10 + struct timeval *timeout)
  11 +{
  12 +#ifdef WIN32
  13 + /*
  14 + * Winsock select() returns WSAEINVAL (10022) when all three
  15 + * fd_sets are empty.
  16 + *
  17 + * The VM uses select() with empty fd_sets as a timer.
  18 + * To preserve the POSIX behaviour, use one private socket
  19 + * as a dummy descriptor in this specific case.
  20 + */
  21 +
  22 + bool empty =
  23 + (readfds == NULL || readfds->fd_count == 0) &&
  24 + (writefds == NULL || writefds->fd_count == 0) &&
  25 + (exceptfds == NULL || exceptfds->fd_count == 0);
  26 +
  27 + if (empty)
  28 + {
  29 + static SOCKET timer_socket = INVALID_SOCKET;
  30 +
  31 + /*
  32 + * Create the dummy socket once.
  33 + */
  34 + if (timer_socket == INVALID_SOCKET)
  35 + {
  36 + timer_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  37 +
  38 + if (timer_socket == INVALID_SOCKET)
  39 + {
  40 + return SOCKET_ERROR;
  41 + }
  42 + }
  43 +
  44 + fd_set timer_set;
  45 +
  46 + FD_ZERO(&timer_set);
  47 + FD_SET(timer_socket, &timer_set);
  48 +
  49 + /*
  50 + * select() will now simply wait for the timeout because
  51 + * the dummy UDP socket has no expected input.
  52 + *
  53 + * nfds is ignored by Winsock, as usual.
  54 + */
  55 + return select(0,&timer_set, NULL, NULL, timeout);
  56 + }
  57 + return select(nfds, readfds, writefds, exceptfds, timeout);
  58 +
  59 +#else
  60 + return select(nfds, readfds, writefds, exceptfds, timeout);
  61 +#endif
  62 +}
  63 +
  64 +int vm_socket_sendto(
  65 + int fd,
  66 + const void *data,
  67 + int length,
  68 + int flags,
  69 + const struct sockaddr *addr,
  70 + int addrlen)
  71 +{
  72 +#ifdef WIN32
  73 +
  74 + int r = sendto(
  75 + (SOCKET)fd,
  76 + (const char *)data,
  77 + (size_t)length,
  78 + flags,
  79 + addr,
  80 + addrlen);
  81 +
  82 + return r;
  83 +
  84 +#else
  85 +
  86 + return (int)sendto(
  87 + fd,
  88 + data,
  89 + (size_t)length,
  90 + flags,
  91 + addr,
  92 + addrlen);
  93 +
  94 +#endif
  95 +}
0 96 \ No newline at end of file
... ...
anubis_dev/vm/src/vm_socket.h 0 → 100644
  1 +
  2 +#ifndef VM_SOCKET_H
  3 +#define VM_SOCKET_H
  4 +
  5 +#ifdef WIN32
  6 +
  7 +#include <winsock2.h>
  8 +
  9 +#else
  10 +
  11 +#include <sys/types.h>
  12 +#include <sys/socket.h>
  13 +#include <sys/select.h>
  14 +#include <sys/time.h>
  15 +#include <unistd.h>
  16 +
  17 +#endif
  18 +
  19 +#ifdef WIN32
  20 +typedef SOCKET vm_socket_t;
  21 +#else
  22 +typedef int vm_socket_t;
  23 +#endif
  24 +
  25 +
  26 +
  27 +int vm_socket_select(
  28 + int nfds,
  29 + fd_set *readfds,
  30 + fd_set *writefds,
  31 + fd_set *exceptfds,
  32 + struct timeval *timeout);
  33 +
  34 +
  35 +int vm_socket_close(int fd);
  36 +
  37 +
  38 +int vm_socket_send(
  39 + int fd,
  40 + const void *buffer,
  41 + int length);
  42 +
  43 +
  44 +int vm_socket_recv(
  45 + int fd,
  46 + void *buffer,
  47 + int length);
  48 +
  49 +
  50 +int vm_socket_sendto(
  51 + int fd,
  52 + const void *buffer,
  53 + int length,
  54 + int flags,
  55 + const struct sockaddr *addr,
  56 + int addrlen);
  57 +
  58 +int vm_socket_create_wakeup_pair(
  59 + int sockets[2]);
  60 +
  61 +
  62 +#endif
0 63 \ No newline at end of file
... ...
anubis_dev/vm/src/vmtools.cpp
... ... @@ -1347,11 +1347,6 @@ U32 anubis_mcons3(U32 h, U32 t, U32 u, U32 index, AnubisAllocator *allocator)
1347 1347 }
1348 1348  
1349 1349  
1350   -
1351   -
1352   -
1353   -
1354   -
1355 1350 /*************** Connections tools ***************************/
1356 1351  
1357 1352  
... ... @@ -1459,11 +1454,6 @@ open_IP_connection(U32 conn_seg,
1459 1454 // the_linger.l_linger = 2; /* timeout = 2 sec */
1460 1455 // setsockopt(sock, SOL_SOCKET,SO_LINGER,(char*)&the_linger,sizeof(struct linger));
1461 1456  
1462   -printf("NEW TCP SOCKET fd=%d global IN=%d OUT=%d\n",
1463   - sock,
1464   - FD_ISSET(sock, &descriptors_waited_for_input),
1465   - FD_ISSET(sock, &descriptors_waited_for_output));
1466   -fflush(stdout);
1467 1457  
1468 1458 /* make the socket non blocking (this is required to
1469 1459 make connect return immediately) */
... ...