Changeset 60066 in vbox for trunk/src/VBox/Main
- Timestamp:
- Mar 16, 2016 6:28:40 PM (9 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/ClientWatcher.h
r60062 r60066 80 80 81 81 static DECLCALLBACK(int) worker(RTTHREAD hThreadSelf, void *pvUser); 82 uint32_t reapProcesses(void); 82 83 83 84 VirtualBox *mVirtualBox; -
trunk/src/VBox/Main/src-server/ClientWatcher.cpp
r60062 r60066 164 164 { 165 165 AssertReturnVoid(mThread != NIL_RTTHREAD); 166 /* @todo r=klaus, do the reaping on all platforms! */167 #ifndef RT_OS_WINDOWS168 166 AutoWriteLock alock(mLock COMMA_LOCKVAL_SRC_POS); 169 167 mProcesses.push_back(pid); 170 #endif 168 } 169 170 /** 171 * Reaps dead processes in the mProcesses list. 172 * 173 * @returns Number of reaped processes. 174 */ 175 uint32_t VirtualBox::ClientWatcher::reapProcesses(void) 176 { 177 uint32_t cReaped = 0; 178 179 AutoWriteLock alock(mLock COMMA_LOCKVAL_SRC_POS); 180 if (mProcesses.size()) 181 { 182 LogFlowFunc(("UPDATE: child process count = %zu\n", mProcesses.size())); 183 VirtualBox::ClientWatcher::ProcessList::iterator it = mProcesses.begin(); 184 while (it != mProcesses.end()) 185 { 186 RTPROCESS pid = *it; 187 RTPROCSTATUS Status; 188 int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &Status); 189 if (vrc == VINF_SUCCESS) 190 { 191 if ( Status.enmReason != RTPROCEXITREASON_NORMAL 192 || Status.iStatus != RTEXITCODE_SUCCESS) 193 { 194 switch (Status.enmReason) 195 { 196 default: 197 case RTPROCEXITREASON_NORMAL: 198 LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n", 199 pid, pid, Status.iStatus, Status.iStatus)); 200 break; 201 case RTPROCEXITREASON_ABEND: 202 LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n", 203 pid, pid, Status.iStatus, Status.iStatus)); 204 break; 205 case RTPROCEXITREASON_SIGNAL: 206 LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n", 207 pid, pid, Status.iStatus, Status.iStatus)); 208 break; 209 } 210 } 211 else 212 LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n", pid, pid, Status.iStatus, Status.enmReason)); 213 it = mProcesses.erase(it); 214 cReaped++; 215 } 216 else 217 { 218 LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n", pid, pid, vrc)); 219 if (vrc != VERR_PROCESS_RUNNING) 220 { 221 /* remove the process if it is not already running */ 222 it = mProcesses.erase(it); 223 cReaped++; 224 } 225 else 226 ++it; 227 } 228 } 229 } 230 231 return cReaped; 171 232 } 172 233 … … 325 386 #if defined(RT_OS_WINDOWS) 326 387 327 /// @todo (dmik) processes reaping!328 329 388 int vrc; 330 389 … … 341 400 do 342 401 { 402 /* VirtualBox has been early uninitialized, terminate. */ 343 403 AutoCaller autoCaller(that->mVirtualBox); 344 /* VirtualBox has been early uninitialized, terminate */345 404 if (!autoCaller.isOk()) 346 405 break; 347 406 348 bool fPidRace = false; 349 do 407 bool fPidRace = false; /* We poll if the PID of a spawning session hasn't been established yet. */ 408 bool fRecentDeath = false; /* We slowly poll if a session has recently been closed to do reaping. */ 409 for (;;) 350 410 { 351 411 /* release the caller to let uninit() ever proceed */ … … 354 414 /* Kick of the waiting. */ 355 415 uint32_t const cSubworkers = (that->mcWaitHandles + CW_MAX_HANDLES_PER_THREAD - 1) / CW_MAX_HANDLES_PER_THREAD; 356 uint32_t const cMsWait = !fPidRace ? INFINITE : 500;416 uint32_t const cMsWait = fPidRace ? 500 : fRecentDeath ? 5000 : INFINITE; 357 417 LogFlowFunc(("UPDATE: Waiting. %u handles, %u subworkers, %u ms wait\n", that->mcWaitHandles, cSubworkers, cMsWait)); 358 418 … … 404 464 if (!autoCaller.isOk()) 405 465 break; 466 fRecentDeath = false; 406 467 for (uint32_t iSubworker = 0; iSubworker < cSubworkers; iSubworker++) 407 468 { … … 423 484 LogFlowFunc(("UPDATE: Calling i_checkForDeath on idxMachine=%u (idxHandle=%u) dwWait=%#x\n", 424 485 idxMachine, idxHandle, dwWait)); 425 (machines[idxMachine])->i_checkForDeath();486 fRecentDeath |= (machines[idxMachine])->i_checkForDeath(); 426 487 } 427 488 else if (idxMachine < cnt + cntSpawned) … … 431 492 LogFlowFunc(("UPDATE: Calling i_checkForSpawnFailure on idxMachine=%u/%u idxHandle=%u dwWait=%#x\n", 432 493 idxMachine, idxMachine - cnt, idxHandle, dwWait)); 433 (spawnedMachines[idxMachine - cnt])->i_checkForSpawnFailure();494 fRecentDeath |= (spawnedMachines[idxMachine - cnt])->i_checkForSpawnFailure(); 434 495 } 435 496 else … … 533 594 else 534 595 LogFlowFunc(("UPDATE: No update pending.\n")); 535 } 536 while (true); 537 } 538 while (0); 596 597 /* reap child processes */ 598 that->reapProcesses(); 599 600 } /* for ever (well, till autoCaller fails). */ 601 602 } while (0); 539 603 540 604 /* Terminate subworker threads. */ … … 564 628 #elif defined(RT_OS_OS2) 565 629 566 /// @todo (dmik) processes reaping!567 568 630 /* according to PMREF, 64 is the maximum for the muxwait list */ 569 631 SEMRECORD handles[64]; … … 578 640 break; 579 641 580 do642 for (;;) 581 643 { 582 644 /* release the caller to let uninit() ever proceed */ … … 752 814 } 753 815 } 754 } 755 while (true); 756 } 757 while (0); 816 817 /* reap child processes */ 818 that->reapProcesses(); 819 820 } /* for ever (well, till autoCaller fails). */ 821 822 } while (0); 758 823 759 824 /* close the muxsem */ … … 865 930 866 931 /* reap child processes */ 867 { 868 AutoWriteLock alock(that->mLock COMMA_LOCKVAL_SRC_POS); 869 if (that->mProcesses.size()) 870 { 871 LogFlowFunc(("UPDATE: child process count = %d\n", 872 that->mProcesses.size())); 873 VirtualBox::ClientWatcher::ProcessList::iterator it = that->mProcesses.begin(); 874 while (it != that->mProcesses.end()) 875 { 876 RTPROCESS pid = *it; 877 RTPROCSTATUS status; 878 int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &status); 879 if (vrc == VINF_SUCCESS) 880 { 881 if ( status.enmReason != RTPROCEXITREASON_NORMAL 882 || status.iStatus != RTEXITCODE_SUCCESS) 883 { 884 switch (status.enmReason) 885 { 886 default: 887 case RTPROCEXITREASON_NORMAL: 888 LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n", 889 pid, pid, status.iStatus, status.iStatus)); 890 break; 891 case RTPROCEXITREASON_ABEND: 892 LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n", 893 pid, pid, status.iStatus, status.iStatus)); 894 break; 895 case RTPROCEXITREASON_SIGNAL: 896 LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n", 897 pid, pid, status.iStatus, status.iStatus)); 898 break; 899 } 900 } 901 else 902 LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n", 903 pid, pid, status.iStatus, 904 status.enmReason)); 905 it = that->mProcesses.erase(it); 906 } 907 else 908 { 909 LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n", 910 pid, pid, vrc)); 911 if (vrc != VERR_PROCESS_RUNNING) 912 { 913 /* remove the process if it is not already running */ 914 it = that->mProcesses.erase(it); 915 } 916 else 917 ++it; 918 } 919 } 920 } 921 } 932 that->reapProcesses(); 922 933 } 923 934 while (true); … … 1013 1024 1014 1025 /* reap child processes */ 1015 { 1016 AutoWriteLock alock(that->mLock COMMA_LOCKVAL_SRC_POS); 1017 if (that->mProcesses.size()) 1018 { 1019 LogFlowFunc(("UPDATE: child process count = %d\n", 1020 that->mProcesses.size())); 1021 VirtualBox::ClientWatcher::ProcessList::iterator it = that->mProcesses.begin(); 1022 while (it != that->mProcesses.end()) 1023 { 1024 RTPROCESS pid = *it; 1025 RTPROCSTATUS status; 1026 int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &status); 1027 if (vrc == VINF_SUCCESS) 1028 { 1029 if ( status.enmReason != RTPROCEXITREASON_NORMAL 1030 || status.iStatus != RTEXITCODE_SUCCESS) 1031 { 1032 switch (status.enmReason) 1033 { 1034 default: 1035 case RTPROCEXITREASON_NORMAL: 1036 LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n", 1037 pid, pid, status.iStatus, status.iStatus)); 1038 break; 1039 case RTPROCEXITREASON_ABEND: 1040 LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n", 1041 pid, pid, status.iStatus, status.iStatus)); 1042 break; 1043 case RTPROCEXITREASON_SIGNAL: 1044 LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n", 1045 pid, pid, status.iStatus, status.iStatus)); 1046 break; 1047 } 1048 } 1049 else 1050 LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n", 1051 pid, pid, status.iStatus, 1052 status.enmReason)); 1053 it = that->mProcesses.erase(it); 1054 } 1055 else 1056 { 1057 LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n", 1058 pid, pid, vrc)); 1059 if (vrc != VERR_PROCESS_RUNNING) 1060 { 1061 /* remove the process if it is not already running */ 1062 it = that->mProcesses.erase(it); 1063 } 1064 else 1065 ++it; 1066 } 1067 } 1068 } 1069 } 1026 that->reapProcesses(); 1070 1027 } 1071 1028 while (true);
Note:
See TracChangeset
for help on using the changeset viewer.