@@ -279,7 +279,7 @@ pty_posix_spawn(char** argv, char** env,
279279 const struct winsize *winp,
280280 int * master,
281281 pid_t * pid,
282- int * err);
282+ std::string * err);
283283#endif
284284
285285struct DelBuf {
@@ -388,7 +388,7 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) {
388388 std::string helper_path = info[9 ].As <Napi::String>();
389389
390390 pid_t pid;
391- int master;
391+ int master = - 1 ;
392392#if defined(__APPLE__)
393393 int argc = argv_.Length ();
394394 int argl = argc + 4 ;
@@ -403,10 +403,13 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) {
403403 argv[i + 3 ] = strdup (arg.c_str ());
404404 }
405405
406- int err = - 1 ;
406+ std::string err;
407407 pty_posix_spawn (argv, env, term, &winp, &master, &pid, &err);
408- if (err != 0 ) {
409- throw Napi::Error::New (napiEnv, std::string (" pty_posix_spawn failed with error: " ) + std::to_string (err) + " (" + strerror (err) + " )" );
408+ if (!err.empty ()) {
409+ if (master != -1 ) {
410+ close (master);
411+ }
412+ throw Napi::Error::New (napiEnv, err);
410413 }
411414 if (pty_nonblock (master) == -1 ) {
412415 throw Napi::Error::New (napiEnv, " Could not set master fd to nonblocking." );
@@ -725,15 +728,26 @@ pty_getproc(int fd, char *tty) {
725728#endif
726729
727730#if defined(__APPLE__)
731+ static std::string format_error (const char * func, int err_code) {
732+ char buf[256 ];
733+ snprintf (buf, sizeof (buf), " %s: %s" , func, strerror (err_code));
734+ return buf;
735+ }
736+
728737static void
729738pty_posix_spawn (char ** argv, char ** env,
730739 const struct termios *termp,
731740 const struct winsize *winp,
732741 int * master,
733742 pid_t * pid,
734- int * err) {
743+ std::string * err) {
735744 int low_fds[3 ];
736745 size_t count = 0 ;
746+ int res = 0 ;
747+ int slave = -1 ;
748+ char slave_pty_name[128 ];
749+ int spawn_err;
750+ sigset_t signal_set;
737751
738752 for (; count < 3 ; count++) {
739753 low_fds[count] = posix_openpt (O_RDWR);
@@ -745,82 +759,103 @@ pty_posix_spawn(char** argv, char** env,
745759 POSIX_SPAWN_SETSIGDEF |
746760 POSIX_SPAWN_SETSIGMASK |
747761 POSIX_SPAWN_SETSID;
762+
763+ posix_spawn_file_actions_t acts;
764+ posix_spawn_file_actions_init (&acts);
765+
766+ posix_spawnattr_t attrs;
767+ posix_spawnattr_init (&attrs);
768+
748769 *master = posix_openpt (O_RDWR);
749770 if (*master == -1 ) {
750- return ;
771+ *err = format_error (" posix_openpt failed" , errno);
772+ goto done;
751773 }
752774
753- int res = grantpt (*master) || unlockpt (*master);
775+ res = grantpt (*master);
754776 if (res == -1 ) {
755- return ;
777+ *err = format_error (" grantpt failed" , errno);
778+ goto done;
779+ }
780+
781+ res = unlockpt (*master);
782+ if (res == -1 ) {
783+ *err = format_error (" unlockpt failed" , errno);
784+ goto done;
756785 }
757786
758787 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
759- int slave;
760- char slave_pty_name[128 ];
761788 res = ioctl (*master, TIOCPTYGNAME, slave_pty_name);
762789 if (res == -1 ) {
763- return ;
790+ *err = format_error (" ioctl(TIOCPTYGNAME) failed" , errno);
791+ goto done;
764792 }
765793
766794 slave = open (slave_pty_name, O_RDWR | O_NOCTTY);
767795 if (slave == -1 ) {
768- return ;
796+ *err = format_error (" open slave pty failed" , errno);
797+ goto done;
769798 }
770799
771800 if (termp) {
772801 res = tcsetattr (slave, TCSANOW, termp);
773802 if (res == -1 ) {
774- return ;
803+ *err = format_error (" tcsetattr failed" , errno);
804+ goto done;
775805 };
776806 }
777807
778808 if (winp) {
779809 res = ioctl (slave, TIOCSWINSZ, winp);
780810 if (res == -1 ) {
781- return ;
811+ *err = format_error (" ioctl(TIOCSWINSZ) failed" , errno);
812+ goto done;
782813 }
783814 }
784815
785- posix_spawn_file_actions_t acts;
786- posix_spawn_file_actions_init (&acts);
787816 posix_spawn_file_actions_adddup2 (&acts, slave, STDIN_FILENO);
788817 posix_spawn_file_actions_adddup2 (&acts, slave, STDOUT_FILENO);
789818 posix_spawn_file_actions_adddup2 (&acts, slave, STDERR_FILENO);
790819 posix_spawn_file_actions_addclose (&acts, slave);
791820 posix_spawn_file_actions_addclose (&acts, *master);
792821
793- posix_spawnattr_t attrs;
794- posix_spawnattr_init (&attrs);
795- *err = posix_spawnattr_setflags (&attrs, flags);
796- if (*err != 0 ) {
822+ spawn_err = posix_spawnattr_setflags (&attrs, flags);
823+ if (spawn_err != 0 ) {
824+ *err = format_error (" posix_spawnattr_setflags failed" , spawn_err);
797825 goto done;
798826 }
799827
800- sigset_t signal_set;
801828 /* Reset all signal the child to their default behavior */
802829 sigfillset (&signal_set);
803- *err = posix_spawnattr_setsigdefault (&attrs, &signal_set);
804- if (*err != 0 ) {
830+ spawn_err = posix_spawnattr_setsigdefault (&attrs, &signal_set);
831+ if (spawn_err != 0 ) {
832+ *err = format_error (" posix_spawnattr_setsigdefault failed" , spawn_err);
805833 goto done;
806834 }
807835
808836 /* Reset the signal mask for all signals */
809837 sigemptyset (&signal_set);
810- *err = posix_spawnattr_setsigmask (&attrs, &signal_set);
811- if (*err != 0 ) {
838+ spawn_err = posix_spawnattr_setsigmask (&attrs, &signal_set);
839+ if (spawn_err != 0 ) {
840+ *err = format_error (" posix_spawnattr_setsigmask failed" , spawn_err);
812841 goto done;
813842 }
814843
815844 do
816- *err = posix_spawn (pid, argv[0 ], &acts, &attrs, argv, env);
817- while (*err == EINTR);
845+ spawn_err = posix_spawn (pid, argv[0 ], &acts, &attrs, argv, env);
846+ while (spawn_err == EINTR);
847+ if (spawn_err != 0 ) {
848+ *err = format_error (" posix_spawn failed" , spawn_err);
849+ }
818850done:
819851 posix_spawn_file_actions_destroy (&acts);
820852 posix_spawnattr_destroy (&attrs);
853+ if (slave != -1 ) {
854+ close (slave);
855+ }
821856
822- for (; count > 0 ; count-- ) {
823- close (low_fds[count ]);
857+ for (size_t i = 0 ; i <= count; i++ ) {
858+ close (low_fds[i ]);
824859 }
825860}
826861#endif
0 commit comments