| 1883 | } |
| 1884 | |
| 1885 | bool Sys::processHasChildren( ProcessID pid ) { |
| 1886 | #if EE_PLATFORM == EE_PLATFORM_WIN |
| 1887 | HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); |
| 1888 | if ( hSnapshot == INVALID_HANDLE_VALUE ) { |
| 1889 | return false; |
| 1890 | } |
| 1891 | |
| 1892 | PROCESSENTRY32 pe32; |
| 1893 | pe32.dwSize = sizeof( PROCESSENTRY32 ); |
| 1894 | |
| 1895 | if ( !Process32First( hSnapshot, &pe32 ) ) { |
| 1896 | CloseHandle( hSnapshot ); |
| 1897 | return false; |
| 1898 | } |
| 1899 | |
| 1900 | do { |
| 1901 | if ( pe32.th32ParentProcessID == static_cast<DWORD>( pid ) ) { |
| 1902 | CloseHandle( hSnapshot ); |
| 1903 | return true; // Found a child |
| 1904 | } |
| 1905 | } while ( Process32Next( hSnapshot, &pe32 ) ); |
| 1906 | |
| 1907 | CloseHandle( hSnapshot ); |
| 1908 | return false; |
| 1909 | #elif EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_ANDROID |
| 1910 | DIR* dir = opendir( "/proc" ); |
| 1911 | if ( !dir ) { |
| 1912 | return false; |
| 1913 | } |
| 1914 | |
| 1915 | struct dirent* entry; |
| 1916 | while ( ( entry = readdir( dir ) ) != nullptr ) { |
| 1917 | char* endptr; |
| 1918 | long tpid = strtol( entry->d_name, &endptr, 10 ); |
| 1919 | if ( *endptr != '\0' || tpid <= 0 ) { // Skip if not a valid PID directory |
| 1920 | continue; |
| 1921 | } |
| 1922 | std::string status_path = std::string( "/proc/" ) + entry->d_name + "/status"; |
| 1923 | std::ifstream status_file( status_path ); |
| 1924 | if ( status_file.is_open() ) { |
| 1925 | std::string line; |
| 1926 | while ( std::getline( status_file, line ) ) { |
| 1927 | if ( line.rfind( "PPid:", 0 ) == 0 ) { |
| 1928 | try { |
| 1929 | long ppid = std::stol( line.substr( 5 ) ); |
| 1930 | if ( ppid == (Int64)pid ) { |
| 1931 | closedir( dir ); |
| 1932 | return true; |
| 1933 | } |
| 1934 | } catch ( const std::invalid_argument& ) { |
| 1935 | } |
| 1936 | break; |
| 1937 | } |
| 1938 | } |
| 1939 | } |
| 1940 | } |
| 1941 | |
| 1942 | closedir( dir ); |