1

I have a PERL script that is creating a lot of sockets (around 700 sockets) and then does stuff with those sockets. After that, it uses system(...) command to launch another application which opens even more sockets (like 800 or so) but since the limit on the number of sockets per process is 1024, I exceed the limit and don't get the expected data from the socket number 1024 and onwards.

Now my question is this:

  1. Does the system command make the application launched inherit all the open file descriptors/sockets?
  2. If the answer to the above question is yes, then is there some other way to launch another application such that the launched application does not inherit the file descriptors?
  3. If the answer to 2. is no, then is there some way to close all inherited file descriptors in the child process?
mmtauqir
  • 8,499
  • 9
  • 34
  • 42
  • What is the per-user fd limit, assuming this is a UNIX-like system? – pilcrow Dec 24 '11 at 19:32
  • Is there a limit per user? I did not know that... The limit per process is set at 1024 (so 0 to 1023 work fine, and the 1024 fails)... – mmtauqir Dec 25 '11 at 00:43
  • I mean a user's process may have a resource limit lower than that of the system. Can you print `$^F` right before system()? Can you try `system('ulimit -n; exec your_command ...')` to see the current limit? – pilcrow Dec 25 '11 at 03:07
  • I know the limit is 1024...any ideas on how to increase this limit? – mmtauqir Dec 25 '11 at 03:44

1 Answers1

3

Take a look at the perlvar $^F which controls which file descriptors are set for close-on-exec. The default setting should be closing all those socket descriptors when you call system(), but if not, perhaps $^F isn't set to what you want. A very quick and easy way to tell on a Linux system would be to try this call right before your existing system() call:

system("ls -l /proc/self/fd");

the output of the ls will show you what files were left open when the "ls" command was executed. Most likely you will see that only stdin, stdout, and stderr (descriptors 0, 1, and 2) are open, but if you see your socket descriptors open, I would try setting $^F = 2 and see if that helps.

andy
  • 6,888
  • 1
  • 19
  • 17
  • Just another question out of curiosity...do you know how to close open sockets in the child process in C? – mmtauqir Dec 25 '11 at 20:32
  • Sure, assuming you can't figure out why close-on-exec isn't working (still the best first approach, I think), you could force everything but stdin, stdout, and stderr closed like this: `for (my $fd = 3; $fd < 1024; $fd++) { close(F) if open(F, "<&=$fd"); } ` – andy Dec 26 '11 at 00:25
  • 1
    Ah, didn't notice the "in C" part of your question so gave you the Perl answer. In C, you use the fcntl call to set close-on-exec like this: fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); – andy Dec 26 '11 at 13:32
  • Just noticed a previous stackoverflow discussion you may find useful: http://stackoverflow.com/questions/1643304/how-to-set-close-on-exec-by-default – andy Dec 26 '11 at 14:30
  • I just tried to print `$^F` and its value is already 2. So I don't understand why the process launched using `system` isn't closing those sockets. – mmtauqir Dec 28 '11 at 20:23
  • That is curious. I recommend replacing the system() call with the ls command I wrote in the post to confirm the open file descriptors are really what you think they are. Also, can you confirm that it is the Perl program itself that opens the sockets? $^F won't affect any file descriptors that are already open when the Perl script is executed (i.e. sockets opened by another program before calling the Perl script). – andy Dec 29 '11 at 16:09
  • My work term finished before I could fix the issue...back to school now...thanks for the help anyway! *thumbs up* – mmtauqir Dec 31 '11 at 22:57