Compare View
Commits (2)
-
To achieve that, I started to make abstraction call for socket calls with vm_socket.cpp. For now only the vm_socket_select and vm_socket-sendto exist. It needs more cleanup and implementation to replace all direct socket calls from the VM into that unified calls. Now the scheduler working only with the event and timeout as it was planned from the conception of the VM. No more 100% CPU and waiting process put in running state every time. I think we made anbexec more speedy and efficient.
-
Now the launched anbexec is able to receive any signal like CTRL+C which was not the case before.
Showing
9 changed files
Show diff stats
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(¤t_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(), ¤t_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(¤t_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(), ¤t_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 "C" { |
| 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("[TCP CONNECT] PID=%u IP=%u entering open_tcp_ip_connection\n", 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; | ... | ... |
| 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 | ... | ... |
| 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) */ | ... | ... |