Using signals to unblock calls to msgrcv() in a multi-threaded process (Cygwin v1.7.33)
I have a multi-threaded process running under Cygwin that receives messages from several IPC message queues (built using Cygwin's gcc, version 4.8.3). The listener for each queue runs in its own thread, each of which is created from the main thread. Each listener is using a blocking call to msgrcv(). I want the main thread to be able to use pthread_kill() to send a SIGUSR1 signal to each listening thread to cause it to abandon its call to msgrcv() and then exit. My approach has been to create a signal mask containing just SIGUSR1 and associate this with a signal handler (although the signal handler contains no functionality, since all I need is for the blocking call to msgrcv() to be abandoned). I initially set the signal mask to block in the main thread, which should then be inherited by each of the created listening threads. I only unblock the signal mask around the call to msgrcv() in each listening thread. I have included a simplified version of my code below. I usually don't see any evidence of the SIGUSR1 signal being received by either of the listener threads. Occasionally the first thread unblocks as expected but I have never seen both threads unblock. If I change my code so that there is only a single listener thread, then everything works correctly every time. Changing the msgrcv() call to a sleep call also allows unblocking to occur correctly. Note that this simplified code does not include removal of the created queues (since it never manages to exit anyway) so I manually remove these after each run using the ipcrm command. Example output: Running thread 2 with queue Id = 1441792 Running thread 1 with queue Id = 1179649 About to kill thread 1 Is there an issue with the Cygwin implementation of signal handling, or is there a problem with my code? Any help would be much appreciated. #include #include #include #include #include #include #include using namespace std; void SigHandler(int signal) { } struct message {long id;} msg; static void* threadMain(void* lpParam) { int threadNumber = *(int*)lpParam; // Set a signal mask for this thread with just SIGUSR1 set sigset_t signalMaskUsr; sigemptyset(&signalMaskUsr); sigaddset(&signalMaskUsr, SIGUSR1); try { // Create an IPC message queue key_t key = ftok("/tmp", threadNumber); int id = msgget(key, IPC_CREAT|IPC_EXCL); if (id == -1) throw runtime_error("Failed to create message queue"); cout << "Running thread " << threadNumber << " with queue Id = " << id << endl; // Unblock the signal mask while in the msgrcv() call if (pthread_sigmask(SIG_UNBLOCK, &signalMaskUsr, NULL) != 0) throw runtime_error("Failed to unblock SIGUSR1 message queue"); if (msgrcv(id, (void *)&msg, sizeof(msg), 0, MSG_NOERROR) == -1) throw runtime_error("Failed to receive data on message queue"); if (pthread_sigmask(SIG_BLOCK, &signalMaskUsr, NULL) != 0) throw runtime_error("Failed to block SIGUSR1 message queue"); cout << "Exiting thread (thread number = " << threadNumber << ", queue id = " << id << ")" << endl; } catch (runtime_error& e) { cout << "Error: " << e.what() << endl; } return NULL; } int main() { // Create a signal mask for the main thread with just SIGUSR1 set sigset_t sigMask; sigemptyset(&sigMask); sigaddset(&sigMask, SIGUSR1); // Initially block the SIGUSR1 signal if (pthread_sigmask(SIG_BLOCK, &sigMask, NULL) != 0) throw runtime_error("Failed to initialise signal mask"); // Setup the Signal Handler for the signal mask struct sigaction actionStruct; actionStruct.sa_flags = 0; actionStruct.sa_mask = sigMask; actionStruct.sa_handler = SigHandler; sigaction(SIGUSR1, &actionStruct, NULL); try { // Create two new threads, passing in parameters of '1' and '2' pthread_t h1; pthread_t h2; int t1 = 1; int t2 = 2; if (pthread_create(&h1, NULL, threadMain, (void*)&t1) != 0) throw runtime_error("Failed to create Thread 1"); if (pthread_create(&h2, NULL, threadMain, (void*)&t2) != 0) throw runtime_error("Failed to create Thread 2"); // Allow time for thread creation to have completed sleep(1); cout << "About to kill thread 1" << endl; if (pthread_kill(h1, SIGUSR1) != 0) throw runtime_error("Failed to kill Thread 1"); if (pthread_join(h1, NULL) != 0) throw runtime_error("Failed to join Thread 1"); cout << "About to kill thread 2" << endl; if (pthread_kill(h2, SIGUSR1) != 0) throw runtime_error("Failed to kill Thread 2"); if (pthread_join(h2, NULL) != 0) throw runtime_error("Failed to join Thread 2"); } catch (runtime_error& e) { c
Re: Failure in merging win-env vars into post-'login'...
On Jan 16 17:25, Linda Walsh wrote: > Linda Walsh wrote: > >It *looks*, at this point that my userid isn't being passed from inetd to > >rlogind > >so it can read the ".rhosts" file in my WIN-HOME (USERPROFILE or > >HOMEDRIVE:\HOMEPATH). > > Not quite sure how 'rlogin.exe' as "spawned" by "inetd.exe" > gets my UID as it's env already seems clear (Has PATH(long), SYSTEMDRIVE > SYSTEMROOT and WINDIR)... but nothing identifying my home dir, except > the 'token' as passed from 'inetd.exe' which I re-started manually, > interactively, after re-installing the earlier version of cygwin and > "cycling" all the cygwin processes. > > However 'rlogin' DOES read C:\Users\law.Bliss\.rhosts in the previous > cygwin version (1.7.33-1) and is able to launch 'login' which > launches 'bash' as a login shell w/no PW. So you're running everything under your own account? If so, the new code in Cygwin merging the user env won't help you. The merge only takes place when changing the user context, which usually would occur when login calls bash. Not so in your setup, though. Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpzI5z9NdE8A.pgp Description: PGP signature
Re: Failure in merging win-env vars into post-'login'...
On Jan 16 16:42, Linda Walsh wrote: > Corinna Vinschen wrote: > >On Jan 16 01:43, Linda Walsh wrote: > >> > >>Prior to this, when I logged on using local credentials, I would have a > >>blank hostname. I.e. -- using 'X11' as an example, when I log in > >>locally, I see no hostname in my shell-prompt. > >>But when I log in to another system, then my path is prefixed with the > >>hostname. > >> > >>So... why did I need the local hostname with a "+"?? > > > > Does https://cygwin.com/preliminary-ntsec.html answer that question? > --- > Not entirely. But don't know that it is related to the problem > I'm seeing. It is related to the '+' sign you're seeing in the group names. That's explained in the document. > As it is only being applied to locally created groups, I'm > not going to worry about it too much (i.e. it doesn't interfere with my > samba-3.6.28-winbind credentials, and more interested in why it didn't > look at "/.rhosts" in my home directory.). It seems your home dir is different for some reason. What does your /etc/nsswitch.conf look like (if you have one)? What does getent passwd print in a local mintty session, and what does it print in a remote session via rlogin? Why on earth are you still using rlogin anyway instead of ssh? > It *looks*, at this point that my userid isn't being passed from inetd to > rlogind > so it can read the ".rhosts" file in my WIN-HOME (USERPROFILE or > HOMEDRIVE:\HOMEPATH). Your userid is bound to you token's SID. For accessing .rhosts the home dir in your passwd entry must match. Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpiypJPfp_fw.pgp Description: PGP signature
Re: Using signals to unblock calls to msgrcv() in a multi-threaded process (Cygwin v1.7.33)
On Jan 19 08:29, SCOTT Damien wrote: > I have a multi-threaded process running under Cygwin that receives > messages from several IPC message queues (built using Cygwin's gcc, > version 4.8.3). The listener for each queue runs in its own thread, > each of which is created from the main thread. Each listener is using > a blocking call to msgrcv(). I want the main thread to be able to use > pthread_kill() to send a SIGUSR1 signal to each listening thread to > cause it to abandon its call to msgrcv() and then exit. > > My approach has been to create a signal mask containing just SIGUSR1 > and associate this with a signal handler (although the signal handler > contains no functionality, since all I need is for the blocking call > to msgrcv() to be abandoned). I initially set the signal mask to > block in the main thread, which should then be inherited by each of > the created listening threads. I only unblock the signal mask around > the call to msgrcv() in each listening thread. > > I have included a simplified version of my code below. I usually > don't see any evidence of the SIGUSR1 signal being received by either > of the listener threads. Occasionally the first thread unblocks as > expected but I have never seen both threads unblock. If I change my > code so that there is only a single listener thread, then everything > works correctly every time. Changing the msgrcv() call to a sleep > call also allows unblocking to occur correctly. Note that this > simplified code does not include removal of the created queues (since > it never manages to exit anyway) so I manually remove these after each > run using the ipcrm command. > > Example output: > > Running thread 2 with queue Id = 1441792 > Running thread 1 with queue Id = 1179649 > About to kill thread 1 > > Is there an issue with the Cygwin implementation of signal handling, > or is there a problem with my code? Any help would be much > appreciated. It's an issue with the Cygwin code, probably. The msgrcv code ultimately hangs in a blocking ReadFile call on a named pipe, and this call is non-interruptible. Changing that requires a bigger change in Cygwin which will take time. For the time being, would it be much of a problem for you to convert your stuff to POSIX message queues(*)? These don't require running cygserver, and they are supposed not to suffer from this problem. Fixing them in case of a bug is much easier as well. Corinna (*) http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpuCskVppN00.pgp Description: PGP signature
C++11 thread_local implementation issue on Cygwin/AMD64
Hi. I have hit an issue with thread-local storage variables on Cygwin/AMD64, I do not see it with Cygwin/i686. I am having linking issues when using `thread_local` keyword in Cygwin with its GCC 4.8.3 and GCC 4.9.2. This is derived from log4cplus. The test case is split into three files: File def.hxx: #include namespace N { struct S { std::string str; }; // extern declaration in a header extern thread_local S * ptd; // accessing the extern declared ptd here inline S * get_ptd () { if (! ptd) ptd = new S; return ptd; } } // namespace N File def.cxx: #include "def.hxx" namespace N { // definition of ptd thread_local S * ptd = nullptr; } // namespace N ~~~ File use.cxx: #include "def.hxx" namespace N { __declspec(dllexport) void * foo () { // invoking inline get_ptd() function to get the value in ptd return get_ptd (); } } Now, when I compile each .cxx with `g++ -std=gnu++11 -fvisibility=hidden -c use.cxx def.cxx` and then try to link with `g++ -shared -o cygtest.dll use.o def.o`, I get the following error from linker: use.o:use.cxx:(.text$_ZTWN1N3ptdE[_ZTWN1N3ptdE]+0x15): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `TLS init function for N::ptd' collect2: error: ld returned 1 exit status The nm -C ./def.o output confirms that: `--> nm -C ./def.o b .bss d .data r .rdata r .rdata$zzz t .text 0008 r __emutls_t._ZN1N3ptdE D __emutls_v._ZN1N3ptdE r std::piecewise_construct As you can see, the ptd thread-local variable initialization function is not defined anywhere. The use.o references this initialization function (see bottom of the listing): `--> nm -C ./use.o b .bss d .data i .drectve p .pdata p .pdata$_ZN1N1SC1Ev p .pdata$_ZN1N7get_ptdEv p .pdata$_ZTWN1N3ptdE r .rdata r .rdata$.refptr.__emutls_v._ZN1N3ptdE r .rdata$.refptr._ZTHN1N3ptdE r .rdata$zzz R .refptr.__emutls_v._ZN1N3ptdE R .refptr._ZTHN1N3ptdE t .text t .text$_ZN1N1SC1Ev t .text$_ZN1N7get_ptdEv t .text$_ZTWN1N3ptdE A .weak._ZTHN1N3ptdE._ZN1N1SC1Ev r .xdata r .xdata$_ZN1N1SC1Ev r .xdata$_ZN1N7get_ptdEv r .xdata$_ZTWN1N3ptdE U __emutls_get_address U __emutls_v._ZN1N3ptdE U __gxx_personality_seh0 U __real__ZdlPv U __real__Znwm U _Unwind_Resume U operator delete(void*) T N::S::S() T N::foo() T N::get_ptd() U std::basic_string, std::allocator >::basic_string() U operator new(unsigned long) r std::piecewise_construct w TLS init function for N::ptd T TLS wrapper function for N::ptd Now, this code seems to work well on Linux with both GCC and Clang. Is this a GCC problem on Cygwin? Am I using extern thread_local wrong? My experiments show that not using the extern keyword seems to fix the issue. But I am not sure if that does not introduce two ptd thread-local variables in two TUs. See also http://stackoverflow.com/q/28023728/341065 -- VZ #include "def.hxx" namespace N { thread_local S * ptd = nullptr; } // namespace N #include namespace N { struct S { std::string str; }; extern thread_local S * ptd; inline S * get_ptd () { if (! ptd) ptd = new S; return ptd; } } // namespace N #include "def.hxx" namespace N { __declspec(dllexport) void * foo () { return get_ptd (); } } -- 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
[ANNOUNCEMENT] Updated: stunnel 5.09-1
A new version of stunnel, 5.09-1, is available in the Cygwin distribution. This is a new upstream release, with minor improvements and bug fixes. stunnel is a program that allows you to encrypt arbitrary TCP connections inside TLS (Transport Layer Security, formerly known as Secure Sockets Layer (SSL)). stunnel can allow you to secure non-TLS-aware daemons and protocols (like POP, IMAP, LDAP, etc) by having stunnel provide the encryption, requiring no changes to the daemon's code. Andrew E. Schulman *** To update your installation, click on the "Install Cygwin now" link on the http://cygwin.com/ web page. This downloads setup.exe to your system. Then, run setup and answer all of the questions. *** CYGWIN-ANNOUNCE UNSUBSCRIBE INFO *** If you want to unsubscribe from the cygwin-announce mailing list, look at the "List-Unsubscribe: " tag in the email header of this message. Send email to the address specified there. It will be in the format: cygwin-announce-unsubscribe-you=yourdomain.com_at_cygwin.com If you need more information on unsubscribing, start reading here: http://cygwin.com/lists.html#subscribe-unsubscribe Please read *all* of the information on unsubscribing that is available starting at this URL. -- 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
[ANNOUNCEMENT] Updated: lftp 4.6.1-1
A new version of lftp, 4.6.1-1, is available in the Cygwin distribution. This is a new upstream release with bug fixes. The full changelog is at http://lftp.yar.ru/news.html. lftp is a sophisticated file transfer program and ftp/http/bittorrent client. It supports multiple network protocols. It uses the readline library for input, so it offers tab completion and command history. It has job control and bookmarks. It can mirror sites and transfer multiple files in parallel. It keeps trying interrupted operations until it can complete them. Andrew E. Schulman *** To update your installation, click on the "Install Cygwin now" link on the http://cygwin.com/ web page. This downloads setup.exe to your system. Then, run setup and answer all of the questions. *** CYGWIN-ANNOUNCE UNSUBSCRIBE INFO *** If you want to unsubscribe from the cygwin-announce mailing list, look at the "List-Unsubscribe: " tag in the email header of this message. Send email to the address specified there. It will be in the format: cygwin-announce-unsubscribe-you=yourdomain.com_at_cygwin.com If you need more information on unsubscribing, start reading here: http://cygwin.com/lists.html#subscribe-unsubscribe Please read *all* of the information on unsubscribing that is available starting at this URL. -- 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
Re: Using signals to unblock calls to msgrcv() in a multi-threaded process (Cygwin v1.7.33)
On Jan 19 11:38, Corinna Vinschen wrote: > On Jan 19 08:29, SCOTT Damien wrote: > > I have a multi-threaded process running under Cygwin that receives > > messages from several IPC message queues (built using Cygwin's gcc, > > version 4.8.3). The listener for each queue runs in its own thread, > > each of which is created from the main thread. Each listener is using > > a blocking call to msgrcv(). I want the main thread to be able to use > > pthread_kill() to send a SIGUSR1 signal to each listening thread to > > cause it to abandon its call to msgrcv() and then exit. > > > > My approach has been to create a signal mask containing just SIGUSR1 > > and associate this with a signal handler (although the signal handler > > contains no functionality, since all I need is for the blocking call > > to msgrcv() to be abandoned). I initially set the signal mask to > > block in the main thread, which should then be inherited by each of > > the created listening threads. I only unblock the signal mask around > > the call to msgrcv() in each listening thread. > > > > I have included a simplified version of my code below. I usually > > don't see any evidence of the SIGUSR1 signal being received by either > > of the listener threads. Occasionally the first thread unblocks as > > expected but I have never seen both threads unblock. If I change my > > code so that there is only a single listener thread, then everything > > works correctly every time. Changing the msgrcv() call to a sleep > > call also allows unblocking to occur correctly. Note that this > > simplified code does not include removal of the created queues (since > > it never manages to exit anyway) so I manually remove these after each > > run using the ipcrm command. > > > > Example output: > > > > Running thread 2 with queue Id = 1441792 > > Running thread 1 with queue Id = 1179649 > > About to kill thread 1 > > > > Is there an issue with the Cygwin implementation of signal handling, > > or is there a problem with my code? Any help would be much > > appreciated. > > It's an issue with the Cygwin code, probably. The msgrcv code ultimately > hangs in a blocking ReadFile call on a named pipe, and this call is > non-interruptible. Changing that requires a bigger change in Cygwin > which will take time. ...or not. I'm not sure I can fix that for the upcoming 1.7.34 release, but it seems cygserver is using the wrong signal handle. At one point the signal handling got changed a lot to improve per-thread signalling, and, as far as I can see, the cygserver code still assumes a global per-process signal handle, which is the old version from before the change. Just to let you know I'm looking into that. Stay tuned. Oh, btw., there's a bug in your testcase: int id = msgget(key, IPC_CREAT|IPC_EXCL); This call is missing the permission bits, so the permissions are set to 000. The permission bits should be added: int id = msgget(key, IPC_CREAT|IPC_EXCL|S_IWUSR|S_IRUSR); Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpXx_y1Iride.pgp Description: PGP signature
Re: Using signals to unblock calls to msgrcv() in a multi-threaded process (Cygwin v1.7.33)
On Jan 19 17:21, Corinna Vinschen wrote: > On Jan 19 11:38, Corinna Vinschen wrote: > > On Jan 19 08:29, SCOTT Damien wrote: > > > [...] > > > I have included a simplified version of my code below. I usually > > > don't see any evidence of the SIGUSR1 signal being received by either > > > of the listener threads. Occasionally the first thread unblocks as > > > expected but I have never seen both threads unblock. If I change my > > > code so that there is only a single listener thread, then everything > > > works correctly every time. Changing the msgrcv() call to a sleep > > > call also allows unblocking to occur correctly. Note that this > > > simplified code does not include removal of the created queues (since > > > it never manages to exit anyway) so I manually remove these after each > > > run using the ipcrm command. > > > > > > Example output: > > > > > > Running thread 2 with queue Id = 1441792 > > > Running thread 1 with queue Id = 1179649 > > > About to kill thread 1 > > > > > > Is there an issue with the Cygwin implementation of signal handling, > > > or is there a problem with my code? Any help would be much > > > appreciated. > > > > It's an issue with the Cygwin code, probably. The msgrcv code ultimately > > hangs in a blocking ReadFile call on a named pipe, and this call is > > non-interruptible. Changing that requires a bigger change in Cygwin > > which will take time. > > ...or not. I'm not sure I can fix that for the upcoming 1.7.34 release, > but it seems cygserver is using the wrong signal handle. At one point > the signal handling got changed a lot to improve per-thread signalling, > and, as far as I can see, the cygserver code still assumes a global > per-process signal handle, which is the old version from before the > change. > > Just to let you know I'm looking into that. Stay tuned. > > Oh, btw., there's a bug in your testcase: > > int id = msgget(key, IPC_CREAT|IPC_EXCL); > > This call is missing the permission bits, so the permissions are set > to 000. The permission bits should be added: > > int id = msgget(key, IPC_CREAT|IPC_EXCL|S_IWUSR|S_IRUSR); Well, it was not as complicated as I anticipated. I applied a patch to cygserver to pull it into the wonderful modern times of per-thread signalling. I created and uploaded a new developer snapshot to https://cygwin.com/snapshots/ with this change. Please give it a try and report back. Thanks, Corinna -- Corinna Vinschen Please, send mails regarding Cygwin to Cygwin Maintainer cygwin AT cygwin DOT com Red Hat pgpyP73lLmyns.pgp Description: PGP signature
Re: Using signals to unblock calls to msgrcv() in a multi-threaded process (Cygwin v1.7.33)
On 1/19/2015 8:10 PM, Corinna Vinschen wrote: Well, it was not as complicated as I anticipated. I applied a patch to cygserver to pull it into the wonderful modern times of per-thread signalling. I created and uploaded a new developer snapshot to https://cygwin.com/snapshots/ with this change. Please give it a try and report back. the latest snapshots solve a long standing issue with postgres http://www.postgresql.org/message-id/20140202181323.8089.65...@wrigleys.postgresql.org Thanks, Corinna Thanks Marco -- 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
Calling man from nonexistent directory cause fatal error
Greetings, All! I was doing some cleanup, and accidentally left Cygwin terminal hanging in a directory I've since deleted. When trying to reference bash manual from there, the thing all went down in flames of $ man bash man: can't change directory to '/home/anrdaemon/1': Permission denied man: command exited with status 255: (cd /home/anrdaemon/1 && LESS=-ix8RmPm Manual page bash(1) ?ltline %lt?L/%L.:byte %bB?s/%s..?e (END):?pB %pB\%.. (press h for help or q to quit)$PM Manual page bash(1) ?ltline %lt?L/%L.:byte %bB?s/%s..?e (END):?pB %pB\%.. (press h for help or q to quit)$ MAN_PN=bash(1) less -s) Is this expected behavior? Why it is trying to chdir anywhere, anyway? I can reproduce this from both local and remote filesystems. $ uname -a CYGWIN_NT-6.1 daemon2 1.7.34s(0.283/5/3) 20150108 17:09:28 x86_64 Cygwin Please let me know, if there's any other information you need. The list is known to eat my cygchecks. >.> -- WBR, Andrey Repin (anrdae...@yandex.ru) 20.01.2015, <04:32> Sorry for my terrible english... -- 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
xz update 5.2.0 is available upstream - package maintainer?
Hi, xz 5.2 with cool new parallel compression options is available since about one month. This is a gentle nudge for package maintainer, (whose effort is very appreciated) Was this update noticed please? or How do i identify who maintains a package for cygwin? to guess if the maintainer is still active. Regards mappu P.S. please CC, i'm not subscribed to list -- 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
Re: xz update 5.2.0 is available upstream - package maintainer?
On Tue, 2015-01-20 at 19:36 +1300, mappu wrote: > xz 5.2 with cool new parallel compression options is available since > about one month. > > This is a gentle nudge for package maintainer, (whose effort is very > appreciated) Was this update noticed please? It was, but it just hit rawhide a few days ago. I do have an update to 5.0.8 -- released upstream the very same day -- in the queue, but given the new features, I'm planning on letting it get some more testing first. There's also the issue of assuring that setup*.exe can handle parallel-compressed .tar.xz, as there was previously an issue with pbzip2 parallel compression. > or How do i identify who maintains a package for cygwin? to guess if the > maintainer is still active. https://cygwin.com/cygwin-pkg-maint Note that this is NOT an invitation to contact maintainers privately. -- Yaakov -- 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