public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* 1.7.9: spawn brakes reopening of serial port
@ 2011-10-20  8:22 Manuel Wienand
  2011-10-21 10:50 ` Corinna Vinschen
  0 siblings, 1 reply; 4+ messages in thread
From: Manuel Wienand @ 2011-10-20  8:22 UTC (permalink / raw)
  To: cygwin

Hallo,

it seems that spawning a process brakes the reopening of a serial port (when done during the execution of that process). The result of the open() function is "Permission denied (13)" in that case.

How to test:
Run the following code ;)
TestSharedMemProc is the process that should be spawned by TestSharedMem (yes, the name is misleading, but it's just a test...).

First I had shm_open under investigation for my problem, because sometimes I got a "Bad Address" (EFAULT, 14) error, but I couldn't reproduce it with a small program and I'm not sure if the problem is somehow connected to the serial port problem. In my original program I got it when opening the shared memory in the spawned (child) process. The shared memory was created in the parent process first and did exist in /dev/shm.
shm_open() returning EFAULT seems to be cygwin specific; what could have caused it? Maybe with a hint in the right direction I might be able to reproduce the error as well.

Thanks,
Manuel

/*
 ============================================================================
 Name        : TestSharedMem.c
 ============================================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#define COMPORT_NAME      "/dev/com1"
#define SPAWN_FILE_NAME   "./TestSharedMemProc.exe"

int serialportHandle = -1;

int SC_Close()
{
  if( serialportHandle >= 0 )
  {
    fprintf(stdout, "Closing handle %d.\n", serialportHandle);
    if( close(serialportHandle) < 0 )
    {
      fprintf(stdout, "Couldn't close COM-Port: %s :%d \n",sys_errlist[errno],errno);
      return 3;
    }
  }
  serialportHandle = -1;

  return 0;
}

int SC_Open()
{

  // Close any already open connections first
  if( serialportHandle >= 0)
  {
    fprintf(stdout, "Open called before closing the port. Closing the port now.\n");
    SC_Close();
  }

  // Call open to open a port
  serialportHandle = open(COMPORT_NAME, O_RDWR | O_NONBLOCK );
  if( serialportHandle < 0 )
  {
    fprintf(stdout, "Couldn't open COM-Port (%s): %s :%d \n",COMPORT_NAME,sys_errlist[errno],errno);
    return 4;
  }

  fprintf(stdout, "Opened port %s (handle %d).\n", COMPORT_NAME, serialportHandle);

  return 0;
}

int main(void) {
	puts("TestSharedMem");
	int error;

  error = SC_Open();
  if (error != 0)
  {
    printf("first open(COM port %s) failed.\n", COMPORT_NAME);
  }

  // Spawn
  //int pid = spawnl(_P_WAIT, SPAWN_FILE_NAME, "TestSharedMemProc", NULL);
  int pid = spawnl(_P_NOWAITO, SPAWN_FILE_NAME, "TestSharedMemProc", NULL);
  if (pid == -1)
  {
    printf( "Failed to create process: %s %d\n", sys_errlist[errno],errno);
  }
  //sleep(2); // If the process closes before the next SC_Open, it works.

  error = SC_Open();
  if (error != 0)
  {
    printf("second open(COM port %s) failed.\n", COMPORT_NAME);
  }

  SC_Close();

  puts("Done (TestSharedMem).");

	return EXIT_SUCCESS;
}

/*
 ============================================================================
 Name        : TestSharedMemProc.c
 ============================================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
	puts("TestSharedMemProc");

  sleep(1); // This process must be running when
            // opening the COM port the second time
            // -> maybe you need to increase the time

  puts("Done (TestSharedMemProc).");

	return 0;
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: 1.7.9: spawn brakes reopening of serial port
  2011-10-20  8:22 1.7.9: spawn brakes reopening of serial port Manuel Wienand
@ 2011-10-21 10:50 ` Corinna Vinschen
  2011-10-24 10:04   ` Manuel Wienand
  0 siblings, 1 reply; 4+ messages in thread
From: Corinna Vinschen @ 2011-10-21 10:50 UTC (permalink / raw)
  To: cygwin

On Oct 20 10:19, Manuel Wienand wrote:
> Hallo,
> 
> it seems that spawning a process brakes the reopening of a serial port
> (when done during the execution of that process). The result of the
> open() function is "Permission denied (13)" in that case.

I had a look into your testcase.  What you see is expected behaviour.

On Windows, a serial port can only be opened once at a time, for
exclusive access.  You could have tried that without starting a second
process:

  open ("/dev/ttyS0", O_RDWR);  // succeeds
  open ("/dev/ttyS0", O_RDWR);  // 2nd call fails with EACCES.

Now I hear you say that you close the descriptor before trying to open
it the second time, but you're missing the fact that on spawn/exec the
child process inherits the open file descriptors from the parent process.
So, even if you close the descriptor in the parent, it's still open in
the child.

Apparently you don't want the child process to inherit this descriptor,
so you must set its "close-on-exec" flag.  There are basically two ways
to do that

 - fd = open ("/dev/ttyS0", O_RDWR | O_CLOEXEC);

 - fd = open ("/dev/ttyS0", O_RDWR);
   fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC);

I guess it goes without saying that the close-on-exec flag has to be
set before calling spawn/exec.

And, btw., please use /dev/ttyS0 rather than /dev/com1, etc.  These are
the "official" names for the serial ports, while the "dev/comX" syntax
is only supported for backward compatibility.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: 1.7.9: spawn brakes reopening of serial port
  2011-10-21 10:50 ` Corinna Vinschen
@ 2011-10-24 10:04   ` Manuel Wienand
  2011-10-24 10:21     ` Corinna Vinschen
  0 siblings, 1 reply; 4+ messages in thread
From: Manuel Wienand @ 2011-10-24 10:04 UTC (permalink / raw)
  To: cygwin

Hallo Corinna,

thanks for the response. Yes, you are right, I missed the fact that the child process inherits the file descriptors.

I took a look at the documentation of exec and just to be clear on the descriptor/handler issue:
- file descriptor are passed down (basically always when calling the 'open' function)
- socket descriptors are *not* passed down (not sure, wasn't in the documentation)
- handles of semaphores, mutexes, memory maps, message queues are *not* passed down.
- signal mask, scheduling policies (at leat when using SCHED_FIFO, SCHED_RR or SCHED_SPORADIC) and directory streams are passed down
Is that correct?

Thanks

Manuel


> -----Original Message-----
> From: *** On Behalf Of Corinna Vinschen
> Sent: Friday, October 21, 2011 12:50 PM
> To: ***
> Subject: Re: 1.7.9: spawn brakes reopening of serial port
> 
> On Oct 20 10:19, Manuel Wienand wrote:
> > Hallo,
> >
> > it seems that spawning a process brakes the reopening of a serial
> port
> > (when done during the execution of that process). The result of the
> > open() function is "Permission denied (13)" in that case.
> 
> I had a look into your testcase.  What you see is expected behaviour.
> 
> On Windows, a serial port can only be opened once at a time, for
> exclusive access.  You could have tried that without starting a second
> process:
> 
>   open ("/dev/ttyS0", O_RDWR);  // succeeds
>   open ("/dev/ttyS0", O_RDWR);  // 2nd call fails with EACCES.
> 
> Now I hear you say that you close the descriptor before trying to open
> it the second time, but you're missing the fact that on spawn/exec the
> child process inherits the open file descriptors from the parent
> process.
> So, even if you close the descriptor in the parent, it's still open in
> the child.
> 
> Apparently you don't want the child process to inherit this descriptor,
> so you must set its "close-on-exec" flag.  There are basically two ways
> to do that
> 
>  - fd = open ("/dev/ttyS0", O_RDWR | O_CLOEXEC);
> 
>  - fd = open ("/dev/ttyS0", O_RDWR);
>    fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC);
> 
> I guess it goes without saying that the close-on-exec flag has to be
> set before calling spawn/exec.
> 
> And, btw., please use /dev/ttyS0 rather than /dev/com1, etc.  These are
> the "official" names for the serial ports, while the "dev/comX" syntax
> is only supported for backward compatibility.
> 
> 
> Corinna
> 
> --
> Corinna Vinschen                  Please, send mails regarding Cygwin
> to
> Cygwin Project Co-Leader          cygwin AT cygwin DOT com
> Red Hat
> 
> --
> Problem reports:       http://cygwin.com/problems.html
> FAQ:                   http://cygwin.com/faq/
> Documentation:         http://cygwin.com/docs.html
> Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
> 
> 
> --
> This message has been scanned for viruses and
> dangerous content by MailScanner, and is
> believed to be clean.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: 1.7.9: spawn brakes reopening of serial port
  2011-10-24 10:04   ` Manuel Wienand
@ 2011-10-24 10:21     ` Corinna Vinschen
  0 siblings, 0 replies; 4+ messages in thread
From: Corinna Vinschen @ 2011-10-24 10:21 UTC (permalink / raw)
  To: cygwin



Please, don't http://cygwin.com/acronyms/#TOFU


On Oct 24 12:02, Manuel Wienand wrote:
> Hallo Corinna,
> 
> thanks for the response. Yes, you are right, I missed the fact that
> the child process inherits the file descriptors.
> 
> I took a look at the documentation of exec and just to be clear on the
> descriptor/handler issue:
> - file descriptor are passed down (basically always when calling the
> 'open' function)
> - socket descriptors are *not* passed down (not sure, wasn't in the
> documentation)

All descriptors are passed down, unless the close-on-exec flag has been
set explicitely.

> - handles of semaphores, mutexes, memory maps, message queues are
> *not* passed down.

Uh, "handles" sounds so much like a Windows concept...
As for POSIX IPC objects, they are not inherited by exec'ed processes
and have to be reopened.

> - signal mask, scheduling policies (at leat when using SCHED_FIFO,
> SCHED_RR or SCHED_SPORADIC) and directory streams are passed down
> Is that correct?

Not quite.  For a good overview of what happens in execve, see
http://www.kernel.org/doc/man-pages/online/pages/man2/execve.2.html


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-10-24 10:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-20  8:22 1.7.9: spawn brakes reopening of serial port Manuel Wienand
2011-10-21 10:50 ` Corinna Vinschen
2011-10-24 10:04   ` Manuel Wienand
2011-10-24 10:21     ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).