Changeset 3447 in kBuild
- Timestamp:
- Sep 11, 2020 1:22:14 PM (5 years ago)
- Location:
- trunk/src/kash
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/shfile.c
r3444 r3447 1050 1050 # endif /* SH_FORKED_MODE */ 1051 1051 1052 /** shfile_exec_win helper that make sure there are no _O_APPEND handles. */ 1053 static KBOOL shfile_exec_win_no_append(shfdtab *pfdtab, unsigned count) 1054 { 1055 unsigned i; 1056 for (i = 0; i < count; i++) 1057 if ( (pfdtab->tab[i].oflags & _O_APPEND) 1058 && (pfdtab->tab[i].oflags & (_O_WRONLY | _O_RDWR))) 1059 return K_FALSE; 1060 return K_TRUE; 1061 } 1062 1052 1063 /** 1053 1064 * Helper for sh_execve. … … 1058 1069 * it will restore the handle inheritability properties. 1059 1070 * 1060 * @returns Pointer to CRT data if prepare is 1, NULL if prepare is 0.1071 * @returns 0 on success, non-zero on failure. 1061 1072 * @param pfdtab The file descriptor table. 1062 1073 * @param prepare Which call, 1 if before, 0 if after and success, -1 if after on failure. 1063 * @param sizep Where to store the size of the returned data.1064 * @param hndls Where to store the three standard handles.1065 */ 1066 void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intptr_t *hndls) 1067 { 1068 void *pvRet;1069 shmtxtmp tmp;1070 unsigned count;1071 unsigned i;1074 * @param info The info structure. 1075 */ 1076 int shfile_exec_win(shfdtab *pfdtab, int prepare, shfdexecwin *info) 1077 { 1078 STARTUPINFOA *strtinfo = (STARTUPINFOA *)info->strtinfo; 1079 int rc = 0; 1080 shmtxtmp tmp; 1081 unsigned count; 1082 unsigned i; 1072 1083 1073 1084 shmtx_enter(&pfdtab->mtx, &tmp); … … 1077 1088 ? pfdtab->size 1078 1089 : (0x10000-4) / (1 + sizeof(HANDLE)); 1079 while (count > 3 && pfdtab->tab[count - 1].fd == -1) 1090 while ( count > 3 1091 && ( pfdtab->tab[count - 1].fd == -1 1092 || (pfdtab->tab[count - 1].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC))) 1080 1093 count--; 1081 1094 1082 1095 if (prepare > 0) 1083 1096 { 1084 size_t cbData = sizeof(int) + count * (1 + sizeof(HANDLE)); 1085 uint8_t *pbData = sh_malloc(shthread_get_shell(), cbData); 1086 uint8_t *paf = pbData + sizeof(int); 1087 HANDLE *pah = (HANDLE *)(paf + count); 1088 1089 *(int *)pbData = count; 1090 1091 i = count; 1092 while (i-- > 0) 1093 { 1094 if ( pfdtab->tab[i].fd == i 1095 && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) 1097 if (count <= 3 && shfile_exec_win_no_append(pfdtab, count)) 1098 { 1099 info->inherithandles = 0; 1100 info->startsuspended = 1; 1101 strtinfo->cbReserved2 = 0; 1102 strtinfo->lpReserved2 = NULL; 1103 } 1104 else 1105 { 1106 size_t cbData = sizeof(int) + count * (1 + sizeof(HANDLE)); 1107 uint8_t *pbData = sh_malloc(shthread_get_shell(), cbData); 1108 uint8_t *paf = pbData + sizeof(int); 1109 HANDLE *pah = (HANDLE *)(paf + count); 1110 1111 info->inherithandles = 1; 1112 info->startsuspended = 0; 1113 strtinfo->cbReserved2 = (unsigned short)cbData; 1114 strtinfo->lpReserved2 = pbData; 1115 1116 shmtx_leave(&pfdtab->mtx, &tmp); /* should be harmless as this isn't really necessary at all. */ 1117 shmtx_enter(&g_sh_exec_inherit_mtx, &info->tmp); 1118 shmtx_enter(&pfdtab->mtx, &tmp); 1119 1120 *(int *)pbData = count; 1121 1122 i = count; 1123 while (i-- > 0) 1096 1124 { 1097 HANDLE hFile = shfile_set_inherit_win(&pfdtab->tab[i], 1); 1098 TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", 1099 i, hFile, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); 1100 paf[i] = FOPEN; 1101 if (pfdtab->tab[i].oflags & _O_APPEND) 1102 paf[i] |= FAPPEND; 1103 if (pfdtab->tab[i].oflags & _O_TEXT) 1104 paf[i] |= FTEXT; 1105 switch (pfdtab->tab[i].shflags & SHFILE_FLAGS_TYPE_MASK) 1125 if ( pfdtab->tab[i].fd == i 1126 && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) 1106 1127 { 1107 case SHFILE_FLAGS_TTY: paf[i] |= FDEV; break; 1108 case SHFILE_FLAGS_PIPE: paf[i] |= FPIPE; break; 1128 HANDLE hFile = shfile_set_inherit_win(&pfdtab->tab[i], 1); 1129 TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", 1130 i, hFile, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); 1131 paf[i] = FOPEN; 1132 if (pfdtab->tab[i].oflags & _O_APPEND) 1133 paf[i] |= FAPPEND; 1134 if (pfdtab->tab[i].oflags & _O_TEXT) 1135 paf[i] |= FTEXT; 1136 switch (pfdtab->tab[i].shflags & SHFILE_FLAGS_TYPE_MASK) 1137 { 1138 case SHFILE_FLAGS_TTY: paf[i] |= FDEV; break; 1139 case SHFILE_FLAGS_PIPE: paf[i] |= FPIPE; break; 1140 } 1141 pah[i] = hFile; 1109 1142 } 1110 pah[i] = hFile; 1143 else 1144 { 1145 paf[i] = 0; 1146 pah[i] = INVALID_HANDLE_VALUE; 1147 } 1148 } 1149 } 1150 1151 for (i = 0; i < 3; i++) 1152 { 1153 if ( i < count 1154 && pfdtab->tab[i].fd == i) 1155 { 1156 info->replacehandles[i] = 1; 1157 info->handles[i] = pfdtab->tab[i].native; 1111 1158 } 1112 1159 else 1113 1160 { 1114 paf[i] = 0;1115 pah[i] =INVALID_HANDLE_VALUE;1161 info->replacehandles[i] = 0; 1162 info->handles[i] = (intptr_t)INVALID_HANDLE_VALUE; 1116 1163 } 1117 }1118 1119 for (i = 0; i < 3; i++)1120 {1121 if ( i < count1122 && pfdtab->tab[i].fd == i)1123 hndls[i] = pfdtab->tab[i].native;1124 else1125 hndls[i] = (intptr_t)INVALID_HANDLE_VALUE;1126 1164 TRACE2((NULL, "shfile_exec_win: i=%d count=%d fd=%d native=%d hndls[%d]=\n", 1127 i, count, pfdtab->tab[i].fd, pfdtab->tab[i].native, i, hndls[i])); 1128 } 1129 1130 *sizep = (unsigned short)cbData; 1131 pvRet = pbData; 1165 i, count, pfdtab->tab[i].fd, pfdtab->tab[i].native, i, info->handles[i])); 1166 } 1132 1167 } 1133 1168 else 1134 1169 { 1135 1170 shfile *file = pfdtab->tab; 1136 assert(!hndls); 1137 assert(!sizep); 1171 1172 sh_free(NULL, strtinfo->lpReserved2); 1173 strtinfo->lpReserved2 = NULL; 1174 1138 1175 i = count; 1139 1176 if (prepare == 0) … … 1151 1188 } 1152 1189 } 1153 else 1190 else if (info->inherithandles) 1154 1191 for (i = 0; i < count; i++, file++) 1155 1192 if ( file->fd == i 1156 1193 && !(file->shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) 1157 1194 shfile_set_inherit_win(file, 0); 1158 pvRet = NULL; 1195 1196 if (info->inherithandles) 1197 shmtx_leave(&g_sh_exec_inherit_mtx, &info->tmp); 1159 1198 } 1160 1199 1161 1200 shmtx_leave(&pfdtab->mtx, &tmp); 1162 return pvRet;1201 return rc; 1163 1202 } 1164 1203 -
trunk/src/kash/shfile.h
r3444 r3447 134 134 void shfile_uninit(shfdtab *); 135 135 void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls); 136 void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intptr_t *hndls); 136 typedef struct shfdexecwin 137 { 138 int inherithandles; 139 int startsuspended; 140 shmtxtmp tmp; 141 int replacehandles[3]; 142 intptr_t handles[3]; 143 void *strtinfo; 144 } shfdexecwin; 145 int shfile_exec_win(shfdtab *pfdtab, int prepare, shfdexecwin *info); 137 146 int shfile_exec_unix(shfdtab *pfdtab); 138 147 -
trunk/src/kash/shinstance.c
r3446 r3447 50 50 #if K_OS == K_OS_WINDOWS 51 51 # include <Windows.h> 52 # include "nt/nt_child_inject_standard_handles.h" 52 53 # ifdef SH_FORKED_MODE 53 54 extern pid_t shfork_do(shinstance *psh); /* shforkA-win.asm */ … … 70 71 #ifndef SH_FORKED_MODE 71 72 /** Mutex serializing exec/spawn to prevent unwanted file inherting. */ 72 s tatic shmtx g_sh_exec_mtx;73 shmtx g_sh_exec_inherit_mtx; 73 74 #endif 74 75 /** The mutex protecting the the globals and some shell instance members (sigs). */ … … 82 83 /** The number of shells. */ 83 84 static int volatile g_num_shells; 85 /* Statistics: Number of subshells spawned. */ 86 static KU64 g_stat_subshells = 0; 87 /* Statistics: Number of program exec'ed. */ 88 static KU64 volatile g_stat_execs = 0; 89 #if K_OS == K_OS_WINDOWS 90 /* Statistics: Number of serialized exec calls. */ 91 static KU64 volatile g_stat_execs_serialized = 0; 92 #endif 84 93 /** Per signal state for determining a common denominator. 85 94 * @remarks defaults and unmasked actions aren't counted. */ … … 172 181 if (psh->rootshell) 173 182 g_sh_root = psh; 183 else 184 g_stat_subshells++; 174 185 175 186 psh->next = NULL; … … 637 648 shmtx_init(&g_sh_mtx); 638 649 #ifndef SH_FORKED_MODE 639 shmtx_init(&g_sh_exec_ mtx);650 shmtx_init(&g_sh_exec_inherit_mtx); 640 651 #endif 641 652 … … 1660 1671 int rc; 1661 1672 1673 g_stat_execs++; 1674 1662 1675 #ifdef DEBUG 1663 1676 /* log it all */ … … 1698 1711 * This ain't quite straight forward on Windows... 1699 1712 */ 1700 #ifndef SH_FORKED_MODE1701 shmtxtmp tmp;1702 #endif1703 1713 PROCESS_INFORMATION ProcInfo; 1704 1714 STARTUPINFO StrtInfo; 1705 intptr_t hndls[3];1715 shfdexecwin fdinfo; 1706 1716 char *cwd = shfile_getcwd(&psh->fdtab, NULL, 0); 1707 1717 char *cmdline; … … 1812 1822 1813 1823 /* File handles. */ 1814 #ifndef SH_FORKED_MODE 1815 shmtx_enter(&g_sh_exec_mtx, &tmp); 1816 #endif 1817 StrtInfo.dwFlags |= STARTF_USESTDHANDLES; 1818 StrtInfo.lpReserved2 = shfile_exec_win(&psh->fdtab, 1 /* prepare */, &StrtInfo.cbReserved2, hndls); 1819 StrtInfo.hStdInput = (HANDLE)hndls[0]; 1820 StrtInfo.hStdOutput = (HANDLE)hndls[1]; 1821 StrtInfo.hStdError = (HANDLE)hndls[2]; 1824 fdinfo.strtinfo = &StrtInfo; 1825 shfile_exec_win(&psh->fdtab, 1 /* prepare */, &fdinfo); 1826 TRACE2((psh, "sh_execve: inherithandles=%d replacehandles={%d,%d,%d} handles={%p,%p,%p} suspended=%d Reserved2=%p LB %#x\n", 1827 fdinfo.inherithandles, fdinfo.replacehandles[0], fdinfo.replacehandles[1], fdinfo.replacehandles[2], 1828 fdinfo.handles[0], fdinfo.handles[1], fdinfo.handles[3], fdinfo.startsuspended, 1829 StrtInfo.lpReserved2, StrtInfo.cbReserved2)); 1830 if (!fdinfo.inherithandles) 1831 { 1832 StrtInfo.dwFlags |= STARTF_USESTDHANDLES; 1833 StrtInfo.hStdInput = INVALID_HANDLE_VALUE; 1834 StrtInfo.hStdOutput = INVALID_HANDLE_VALUE; 1835 StrtInfo.hStdError = INVALID_HANDLE_VALUE; 1836 } 1837 else 1838 { 1839 StrtInfo.dwFlags |= STARTF_USESTDHANDLES; 1840 StrtInfo.hStdInput = (HANDLE)fdinfo.handles[0]; 1841 StrtInfo.hStdOutput = (HANDLE)fdinfo.handles[1]; 1842 StrtInfo.hStdError = (HANDLE)fdinfo.handles[2]; 1843 g_stat_execs_serialized++; 1844 } 1822 1845 1823 1846 /* Get going... */ 1824 rc = CreateProcess(exe, 1825 cmdline, 1826 NULL, /* pProcessAttributes */ 1827 NULL, /* pThreadAttributes */ 1828 TRUE, /* bInheritHandles */ 1829 0, /* dwCreationFlags */ 1830 envblock, 1831 cwd, 1832 &StrtInfo, 1833 &ProcInfo); 1834 1835 shfile_exec_win(&psh->fdtab, rc ? 0 /* done */ : -1 /* done but failed */, NULL, NULL); 1836 #ifndef SH_FORKED_MODE 1837 shmtx_leave(&g_sh_exec_mtx, &tmp); 1838 #endif 1847 rc = CreateProcessA(exe, 1848 cmdline, 1849 NULL, /* pProcessAttributes */ 1850 NULL, /* pThreadAttributes */ 1851 fdinfo.inherithandles, 1852 fdinfo.startsuspended ? CREATE_SUSPENDED : 0, 1853 envblock, 1854 cwd, 1855 &StrtInfo, 1856 &ProcInfo); 1839 1857 if (rc) 1840 1858 { … … 1842 1860 DWORD dwExitCode; 1843 1861 1862 if (fdinfo.startsuspended) 1863 { 1864 char errmsg[512]; 1865 rc = nt_child_inject_standard_handles(ProcInfo.hProcess, fdinfo.replacehandles, (HANDLE*)&fdinfo.handles[0], 1866 errmsg, sizeof(errmsg)); 1867 if (!rc) 1868 { 1869 rc = ResumeThread(ProcInfo.hThread); 1870 if (!rc) 1871 TRACE2((psh, "sh_execve: ResumeThread failed: %u -> errno=ENXIO\n", GetLastError())); 1872 } 1873 else 1874 { 1875 TRACE2((psh, "sh_execve: nt_child_inject_standard_handles failed: %d -> errno=ENXIO; %s\n", rc, errmsg)); 1876 rc = FALSE; 1877 } 1878 errno = ENXIO; 1879 } 1880 1881 shfile_exec_win(&psh->fdtab, rc ? 0 /* done */ : -1 /* done but failed */, &fdinfo); 1882 1844 1883 CloseHandle(ProcInfo.hThread); 1845 dwErr = WaitForSingleObject(ProcInfo.hProcess, INFINITE); 1846 assert(dwErr == WAIT_OBJECT_0); 1847 1848 if (GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) 1884 ProcInfo.hThread = INVALID_HANDLE_VALUE; 1885 if (rc) 1849 1886 { 1850 CloseHandle(ProcInfo.hProcess); 1851 sh__exit(psh, dwExitCode); 1887 /* 1888 * Wait for it and forward the exit code. 1889 */ 1890 dwErr = WaitForSingleObject(ProcInfo.hProcess, INFINITE); 1891 assert(dwErr == WAIT_OBJECT_0); 1892 1893 if (GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) 1894 { 1895 #ifndef SH_FORKED_MODE 1896 /** @todo signal the end of this subshell now, we can do the cleaning up 1897 * after the parent shell has resumed. */ 1898 #endif 1899 CloseHandle(ProcInfo.hProcess); 1900 ProcInfo.hProcess = INVALID_HANDLE_VALUE; 1901 sh__exit(psh, dwExitCode); 1902 } 1903 1904 /* this shouldn't happen... */ 1905 TRACE2((psh, "sh_execve: GetExitCodeProcess failed: %u\n", GetLastError())); 1906 assert(0); 1907 errno = EINVAL; 1852 1908 } 1853 TRACE2((psh, "sh_execve: GetExitCodeProcess failed: %u\n", GetLastError())); 1854 assert(0); 1909 TerminateProcess(ProcInfo.hProcess, 0x40000015); 1855 1910 CloseHandle(ProcInfo.hProcess); 1856 errno = EINVAL;1857 1911 } 1858 1912 else 1859 1913 { 1860 1914 DWORD dwErr = GetLastError(); 1915 1916 shfile_exec_win(&psh->fdtab, -1 /* done but failed */, &fdinfo); 1917 1861 1918 switch (dwErr) 1862 1919 { … … 1865 1922 case ERROR_BAD_EXE_FORMAT: errno = ENOEXEC; break; 1866 1923 case ERROR_INVALID_EXE_SIGNATURE: errno = ENOEXEC; break; 1867 default: 1868 errno = EINVAL; 1869 break; 1924 default: errno = EINVAL; break; 1870 1925 } 1871 1926 TRACE2((psh, "sh_execve: dwErr=%d -> errno=%d\n", dwErr, errno)); 1872 1927 } 1873 1874 1928 } 1875 1929 rc = -1; -
trunk/src/kash/shinstance.h
r3439 r3447 59 59 # define strncasecmp strnicmp 60 60 #endif 61 62 extern shmtx g_sh_exec_inherit_mtx; 61 63 62 64 /**
Note:
See TracChangeset
for help on using the changeset viewer.