Changeset 3460 in kBuild
- Timestamp:
- Sep 15, 2020 12:31:01 PM (5 years ago)
- Location:
- trunk/src/kash
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/shfork-win.c
r3438 r3460 246 246 if (ResumeThread(ProcInfo.hThread) != (DWORD)-1) 247 247 { 248 rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess, K_TRUE);248 rc = sh_add_child(psh, ProcInfo.dwProcessId, ProcInfo.hProcess, NULL); 249 249 if (!rc) 250 250 rc = (int)ProcInfo.dwProcessId; -
trunk/src/kash/shinstance.c
r3459 r3460 73 73 /** Mutex serializing exec/spawn to prevent unwanted file inherting. */ 74 74 shmtx g_sh_exec_inherit_mtx; 75 /** Mutex protecting g_sh_sts_free. */ 76 static shmtx g_sh_sts_mtx; 77 /** List of free subshell status structure (saves CreateEvent calls). */ 78 static shsubshellstatus * volatile g_sh_sts_free = NULL; 75 79 #endif 76 80 /** The mutex protecting the the globals and some shell instance members (sigs). */ … … 708 712 #ifndef SH_FORKED_MODE 709 713 shmtx_init(&g_sh_exec_inherit_mtx); 714 shmtx_init(&g_sh_sts_mtx); 710 715 #endif 711 716 … … 1415 1420 } 1416 1421 1422 #ifndef SH_FORKED_MODE 1423 1424 /** 1425 * Retains a reference to a subshell status structure. 1426 */ 1427 static unsigned shsubshellstatus_retain(shsubshellstatus *sts) 1428 { 1429 unsigned refs = sh_atomic_dec(&sts->refs); 1430 assert(refs > 1); 1431 assert(refs < 16); 1432 return refs; 1433 } 1434 1435 /** 1436 * Releases a reference to a subshell status structure. 1437 */ 1438 static unsigned shsubshellstatus_release(shinstance *psh, shsubshellstatus *sts) 1439 { 1440 unsigned refs = sh_atomic_dec(&sts->refs); 1441 assert(refs < ~(unsigned)0/4); 1442 if (refs == 0) 1443 { 1444 shmtxtmp tmp; 1445 shmtx_enter(&g_sh_sts_mtx, &tmp); 1446 sts->next = g_sh_sts_free; 1447 g_sh_sts_free = sts; 1448 shmtx_leave(&g_sh_sts_mtx, &tmp); 1449 } 1450 return refs; 1451 } 1452 1453 /** 1454 * Creates a subshell status structure. 1455 */ 1456 static shsubshellstatus *shsubshellstatus_create(shinstance *psh, int refs) 1457 { 1458 shsubshellstatus *sts; 1459 1460 /* Check the free list: */ 1461 if (g_sh_sts_free) 1462 { 1463 shmtxtmp tmp; 1464 shmtx_enter(&g_sh_sts_mtx, &tmp); 1465 sts = g_sh_sts_free; 1466 if (sts) 1467 g_sh_sts_free = sts->next; 1468 shmtx_leave(&g_sh_sts_mtx, &tmp); 1469 } 1470 else 1471 sts = NULL; 1472 if (sts) 1473 { 1474 # if K_OS == K_OS_WINDOWS 1475 BOOL rc = ResetEvent((HANDLE)sts->towaiton); 1476 assert(rc); K_NOREF(rc); 1477 # endif 1478 } 1479 else 1480 { 1481 /* Create a new one: */ 1482 sts = (shsubshellstatus *)sh_malloc(psh, sizeof(*sts)); 1483 if (!sts) 1484 return NULL; 1485 # if K_OS == K_OS_WINDOWS 1486 sts->towaiton = (void *)CreateEventW(NULL /*noinherit*/, TRUE /*fManualReset*/, 1487 FALSE /*fInitialState*/, NULL /*pszName*/); 1488 if (!sts->towaiton) 1489 { 1490 assert(0); 1491 sh_free(psh, sts); 1492 return NULL; 1493 } 1494 # endif 1495 } 1496 1497 /* Initialize it: */ 1498 sts->refs = refs; 1499 sts->status = 999999; 1500 sts->done = 0; 1501 sts->next = NULL; 1502 # if K_OS == K_OS_WINDOWS 1503 sts->hThread = 0; 1504 # endif 1505 return sts; 1506 } 1507 1508 #endif /* !SH_FORKED_MODE */ 1509 1417 1510 /** 1418 1511 * Adds a child to the shell … … 1422 1515 * @param psh The shell instance. 1423 1516 * @param pid The child pid. 1424 * @param hChild Windows child handle.1425 * @param fProcess Set if process, clear if thread.1517 * @param hChild Windows child wait handle (process if sts is NULL). 1518 * @param sts Subshell status structure, NULL if progress. 1426 1519 */ 1427 int sh_add_child(shinstance *psh, shpid pid, void *hChild, KBOOL fProcess)1520 int sh_add_child(shinstance *psh, shpid pid, void *hChild, shsubshellstatus *sts) 1428 1521 { 1429 1522 /* get a free table entry. */ … … 1447 1540 #endif 1448 1541 #ifndef SH_FORKED_MODE 1449 psh->children[i]. fProcess = fProcess;1450 #endif 1451 (void)hChild; (void) fProcess;1542 psh->children[i].subshellstatus = sts; 1543 #endif 1544 (void)hChild; (void)sts; 1452 1545 return 0; 1453 1546 } … … 1499 1592 shinstance * volatile volpsh = (shinstance *)user; 1500 1593 shinstance *psh = (shinstance *)user; 1594 shsubshellstatus *sts; 1501 1595 struct jmploc exitjmp; 1502 1596 int iExit; … … 1527 1621 if (iExit == SH_EXIT_ZERO) 1528 1622 iExit = 0; 1623 } 1624 1625 /* Signal parent. */ 1626 sts = psh->subshellstatus; 1627 if (sts) 1628 { 1629 BOOL rc; 1630 HANDLE hThread; 1631 1632 sts->status = W_EXITCODE(iExit, 0); 1633 sts->done = K_TRUE; 1634 rc = SetEvent((HANDLE)sts->towaiton); assert(rc); K_NOREF(rc); 1635 1636 hThread = (HANDLE)sts->hThread; 1637 sts->hThread = 0; 1638 rc = CloseHandle(hThread); assert(rc); 1639 1640 shsubshellstatus_release(psh, sts); 1641 psh->subshellstatus = NULL; 1529 1642 } 1530 1643 … … 1546 1659 { 1547 1660 # ifdef _MSC_VER 1548 unsigned tid = 0;1549 uintptr_t hThread;1550 1661 shpid pid; 1551 1662 1552 pshchild->thread = thread; 1553 pshchild->threadarg = arg; 1554 hThread = _beginthreadex(NULL /*security*/, 0 /*stack_size*/, sh_thread_wrapper, pshchild, 0 /*initflags*/, &tid); 1555 if (hThread == -1) 1556 return -errno; 1557 1558 pid = SHPID_MAKE(SHPID_GET_PID(pshparent->pid), tid); 1559 pshchild->pid = pid; 1560 pshchild->tid = tid; 1561 1562 if (sh_add_child(pshparent, pid, (void *)hThread, K_FALSE) != 0) { 1563 return -ENOMEM; 1564 } 1663 shsubshellstatus *sts = shsubshellstatus_create(pshparent, 2); 1664 pshchild->subshellstatus = sts; 1665 if (sts) 1666 { 1667 unsigned tid = 0; 1668 uintptr_t hThread; 1669 1670 pshchild->thread = thread; 1671 pshchild->threadarg = arg; 1672 1673 hThread = _beginthreadex(NULL /*security*/, 0 /*stack_size*/, sh_thread_wrapper, pshchild, 0 /*initflags*/, &tid); 1674 sts->hThread = hThread; 1675 if (hThread != -1) 1676 { 1677 pid = SHPID_MAKE(SHPID_GET_PID(pshparent->pid), tid); 1678 pshchild->pid = pid; 1679 pshchild->tid = tid; 1680 1681 if (sh_add_child(pshparent, pid, sts->towaiton, sts) == 0) 1682 { 1683 return pid; 1684 } 1685 1686 shsubshellstatus_retain(sts); 1687 pid = -ENOMEM; 1688 } 1689 else 1690 pid = -errno; 1691 shsubshellstatus_release(pshparent, sts); 1692 shsubshellstatus_release(pshparent, sts); 1693 } 1694 else 1695 pid = -ENOMEM; 1565 1696 return pid; 1566 1697 … … 1645 1776 if (i < psh->num_children) 1646 1777 { 1778 BOOL rc; 1647 1779 if (hChild != INVALID_HANDLE_VALUE) 1648 1780 { 1649 1781 DWORD dwExitCode = 127; 1650 1782 #ifndef SH_FORKED_MODE 1651 if (psh->children[i].fProcess ? GetExitCodeProcess(hChild, &dwExitCode) : GetExitCodeThread(hChild, &dwExitCode)) 1652 #else 1783 if (psh->children[i].subshellstatus) 1784 { 1785 rc = psh->children[i].subshellstatus->done; 1786 assert(rc); 1787 if (rc) 1788 { 1789 *statusp = psh->children[i].subshellstatus->status; 1790 pidret = psh->children[i].pid; 1791 } 1792 } 1793 else 1794 #endif 1653 1795 if (GetExitCodeProcess(hChild, &dwExitCode)) 1654 #endif1655 1796 { 1656 1797 pidret = psh->children[i].pid; … … 1663 1804 } 1664 1805 1665 /* remove and close */ 1666 hChild = psh->children[i].hChild; 1806 /* close and remove */ 1807 if (psh->children[i].subshellstatus) 1808 { 1809 shsubshellstatus_release(psh, psh->children[i].subshellstatus); 1810 psh->children[i].subshellstatus = NULL; 1811 } 1812 else 1813 { 1814 rc = CloseHandle(psh->children[i].hChild); 1815 assert(rc); 1816 } 1817 1667 1818 psh->num_children--; 1668 1819 if (i < psh->num_children) 1669 1820 psh->children[i] = psh->children[psh->num_children]; 1670 i = CloseHandle(hChild); assert(i); 1821 psh->children[psh->num_children].hChild = NULL; 1822 psh->children[psh->num_children].subshellstatus = NULL; 1671 1823 } 1672 1824 -
trunk/src/kash/shinstance.h
r3459 r3460 64 64 #endif 65 65 66 #ifndef SH_FORKED_MODE 67 /** 68 * Subshell status. 69 */ 70 typedef struct shsubshellstatus 71 { 72 unsigned volatile refs; /**< Reference counter. */ 73 int volatile status; /**< The exit code. */ 74 KBOOL volatile done; /**< Set if done (valid exit code). */ 75 void *towaiton; /**< Event semaphore / whatever to wait on. */ 76 # if K_OS == K_OS_WINDOWS 77 uintptr_t volatile hThread; /**< The thread handle (child closes this). */ 78 # endif 79 struct shsubshellstatus *next; /**< Next free one on the free chain. */ 80 } shsubshellstatus; 81 #endif 82 66 83 /** 67 84 * A child process. … … 69 86 typedef struct shchild 70 87 { 71 shpid pid;/**< The pid. */88 shpid pid; /**< The pid. */ 72 89 #if K_OS == K_OS_WINDOWS 73 void *hChild; /**< The process handle. */90 void *hChild; /**< The handle to wait on. */ 74 91 #endif 75 92 #ifndef SH_FORKED_MODE 76 KBOOL fProcess; /**< Set if process, clear if internal thread. */93 shsubshellstatus *subshellstatus; /**< Pointer to the subshell status structure. NULL if child process. */ 77 94 #endif 78 95 } shchild; … … 215 232 void *threadarg; /**< The thread argument. */ 216 233 struct jmploc *exitjmp; /**< Long jump target in sh_thread_wrapper for use by sh__exit. */ 234 shsubshellstatus *subshellstatus; /**< Pointer to the subshell status structure (NULL if root). */ 217 235 #endif 218 236 … … 496 514 497 515 /* wait / process */ 498 int sh_add_child(shinstance *psh, shpid pid, void *hChild, KBOOL fProcess);516 int sh_add_child(shinstance *psh, shpid pid, void *hChild, shsubshellstatus *sts); 499 517 #ifdef _MSC_VER 500 518 # include <process.h>
Note:
See TracChangeset
for help on using the changeset viewer.