--- IO-AIO/AIO.pm 2017/06/23 22:33:06 1.273 +++ IO-AIO/AIO.pm 2019/04/03 03:09:04 1.303 @@ -173,7 +173,7 @@ use base 'Exporter'; BEGIN { - our $VERSION = 4.35; + our $VERSION = 4.72; our @AIO_REQ = qw(aio_sendfile aio_seek aio_read aio_write aio_open aio_close aio_stat aio_lstat aio_unlink aio_rmdir aio_readdir aio_readdirx @@ -185,6 +185,7 @@ aio_chmod aio_utime aio_truncate aio_msync aio_mtouch aio_mlock aio_mlockall aio_statvfs + aio_slurp aio_wd); our @EXPORT = (@AIO_REQ, qw(aioreq_pri aioreq_nice)); @@ -193,7 +194,7 @@ nreqs nready npending nthreads max_poll_time max_poll_reqs sendfile fadvise madvise - mmap munmap munlock munlockall); + mmap munmap mremap munlock munlockall); push @AIO_REQ, qw(aio_busy); # not exported @@ -279,16 +280,41 @@ IO::AIO::nreqs IO::AIO::nready IO::AIO::npending + IO::AIO::reinit + + $nfd = IO::AIO::get_fdlimit [EXPERIMENTAL] + IO::AIO::min_fdlimit $nfd [EXPERIMENTAL] IO::AIO::sendfile $ofh, $ifh, $offset, $count IO::AIO::fadvise $fh, $offset, $len, $advice + IO::AIO::mmap $scalar, $length, $prot, $flags[, $fh[, $offset]] IO::AIO::munmap $scalar + IO::AIO::mremap $scalar, $new_length, $flags[, $new_address] IO::AIO::madvise $scalar, $offset, $length, $advice IO::AIO::mprotect $scalar, $offset, $length, $protect IO::AIO::munlock $scalar, $offset = 0, $length = undef IO::AIO::munlockall + # stat extensions + $counter = IO::AIO::st_gen + $seconds = IO::AIO::st_atime, IO::AIO::st_mtime, IO::AIO::st_ctime, IO::AIO::st_btime + ($atime, $mtime, $ctime, $btime, ...) = IO::AIO::st_xtime + $nanoseconds = IO::AIO::st_atimensec, IO::AIO::st_mtimensec, IO::AIO::st_ctimensec, IO::AIO::st_btimensec + $seconds = IO::AIO::st_btimesec + ($atime, $mtime, $ctime, $btime, ...) = IO::AIO::st_xtimensec + + # very much unportable syscalls + IO::AIO::splice $r_fh, $r_off, $w_fh, $w_off, $length, $flags + IO::AIO::tee $r_fh, $w_fh, $length, $flags + $actual_size = IO::AIO::pipesize $r_fh[, $new_size] + ($rfh, $wfh) = IO::AIO::pipe2 [$flags] + $fh = IO::AIO::memfd_create $pathname[, $flags] + $fh = IO::AIO::eventfd [$initval, [$flags]] + $fh = IO::AIO::timerfd_create $clockid[, $flags] + ($cur_interval, $cur_value) = IO::AIO::timerfd_settime $fh, $flags, $new_interval, $nbw_value + ($cur_interval, $cur_value) = IO::AIO::timerfd_gettime $fh + =head2 API NOTES All the C calls are more or less thin wrappers around the syscall @@ -403,7 +429,7 @@ C, C, C, C, C, C, C, C, C, C, C, -C, C, C, C, and C. +C, C, C, C, C and C. =item aio_close $fh, $callback->($status) @@ -539,9 +565,10 @@ =item aio_lstat $fh, $callback->($status) -Works like perl's C or C in void context. The callback will -be called after the stat and the results will be available using C -or C<-s _> etc... +Works almost exactly like perl's C or C in void context. The +callback will be called after the stat and the results will be available +using C or C<-s _> and other tests (with the exception of C<-B> +and C<-T>). The pathname passed to C must be absolute. See API NOTES, above, for an explanation. @@ -559,6 +586,9 @@ C, C, C, C, C, C. +To access higher resolution stat timestamps, see L. + Example: Print the length of F: aio_stat "/etc/passwd", sub { @@ -611,100 +641,16 @@ fsid => 1810 } -Here is a (likely partial - send me updates!) list of fsid values used by -Linux - it is safe to hardcode these when C<$^O> is C: - - 0x0000adf5 adfs - 0x0000adff affs - 0x5346414f afs - 0x09041934 anon-inode filesystem - 0x00000187 autofs - 0x42465331 befs - 0x1badface bfs - 0x42494e4d binfmt_misc - 0x9123683e btrfs - 0x0027e0eb cgroupfs - 0xff534d42 cifs - 0x73757245 coda - 0x012ff7b7 coh - 0x28cd3d45 cramfs - 0x453dcd28 cramfs-wend (wrong endianness) - 0x64626720 debugfs - 0x00001373 devfs - 0x00001cd1 devpts - 0x0000f15f ecryptfs - 0x00414a53 efs - 0x0000137d ext - 0x0000ef53 ext2/ext3/ext4 - 0x0000ef51 ext2 - 0xf2f52010 f2fs - 0x00004006 fat - 0x65735546 fuseblk - 0x65735543 fusectl - 0x0bad1dea futexfs - 0x01161970 gfs2 - 0x47504653 gpfs - 0x00004244 hfs - 0xf995e849 hpfs - 0x00c0ffee hostfs - 0x958458f6 hugetlbfs - 0x2bad1dea inotifyfs - 0x00009660 isofs - 0x000072b6 jffs2 - 0x3153464a jfs - 0x6b414653 k-afs - 0x0bd00bd0 lustre - 0x0000137f minix - 0x0000138f minix 30 char names - 0x00002468 minix v2 - 0x00002478 minix v2 30 char names - 0x00004d5a minix v3 - 0x19800202 mqueue - 0x00004d44 msdos - 0x0000564c novell - 0x00006969 nfs - 0x6e667364 nfsd - 0x00003434 nilfs - 0x5346544e ntfs - 0x00009fa1 openprom - 0x7461636F ocfs2 - 0x00009fa0 proc - 0x6165676c pstorefs - 0x0000002f qnx4 - 0x68191122 qnx6 - 0x858458f6 ramfs - 0x52654973 reiserfs - 0x00007275 romfs - 0x67596969 rpc_pipefs - 0x73636673 securityfs - 0xf97cff8c selinux - 0x0000517b smb - 0x534f434b sockfs - 0x73717368 squashfs - 0x62656572 sysfs - 0x012ff7b6 sysv2 - 0x012ff7b5 sysv4 - 0x01021994 tmpfs - 0x15013346 udf - 0x00011954 ufs - 0x54190100 ufs byteswapped - 0x00009fa2 usbdevfs - 0x01021997 v9fs - 0xa501fcf5 vxfs - 0xabba1974 xenfs - 0x012ff7b4 xenix - 0x58465342 xfs - 0x012fd16d xia - =item aio_utime $fh_or_path, $atime, $mtime, $callback->($status) Works like perl's C function (including the special case of $atime and $mtime being undef). Fractional times are supported if the underlying syscalls support them. -When called with a pathname, uses utimes(2) if available, otherwise -utime(2). If called on a file descriptor, uses futimes(2) if available, -otherwise returns ENOSYS, so this is not portable. +When called with a pathname, uses utimensat(2) or utimes(2) if available, +otherwise utime(2). If called on a file descriptor, uses futimens(2) +or futimes(2) if available, otherwise returns ENOSYS, so this is not +portable. Examples: @@ -873,10 +819,10 @@ =item IO::AIO::READDIR_DENTS -When this flag is off, then the callback gets an arrayref consisting of -names only (as with C), otherwise it gets an arrayref with -C<[$name, $type, $inode]> arrayrefs, each describing a single directory -entry in more detail. +Normally the callback gets an arrayref consisting of names only (as +with C). If this flag is set, then the callback gets an +arrayref with C<[$name, $type, $inode]> arrayrefs, each describing a +single directory entry in more detail: C<$name> is the name of the entry. @@ -886,9 +832,9 @@ C, C, C, C, C. -C means just that: readdir does not know. If you need to -know, you have to run stat yourself. Also, for speed reasons, the C<$type> -scalars are read-only: you can not modify them. +C means just that: readdir does not know. If you need +to know, you have to run stat yourself. Also, for speed/memory reasons, +the C<$type> scalars are read-only: you must not modify them. C<$inode> is the inode number (which might not be exact on systems with 64 bit inode numbers and 32 bit perls). This field has unspecified content on @@ -909,12 +855,14 @@ =item IO::AIO::READDIR_STAT_ORDER When this flag is set, then the names will be returned in an order -suitable for stat()'ing each one. That is, when you plan to stat() -all files in the given directory, then the returned order will likely -be fastest. - -If both this flag and C are specified, then -the likely dirs come first, resulting in a less optimal stat order. +suitable for stat()'ing each one. That is, when you plan to stat() most or +all files in the given directory, then the returned order will likely be +faster. + +If both this flag and C are specified, +then the likely dirs come first, resulting in a less optimal stat order +for stat'ing all entries, but likely a more optimal order for finding +subdirectories. =item IO::AIO::READDIR_FOUND_UNKNOWN @@ -926,11 +874,42 @@ =back +=item aio_slurp $pathname, $offset, $length, $data, $callback->($status) + +Opens, reads and closes the given file. The data is put into C<$data>, +which is resized as required. + +If C<$offset> is negative, then it is counted from the end of the file. + +If C<$length> is zero, then the remaining length of the file is +used. Also, in this case, the same limitations to modifying C<$data> apply +as when IO::AIO::mmap is used, i.e. it must only be modified in-place +with C. If the size of the file is known, specifying a non-zero +C<$length> results in a performance advantage. + +This request is similar to the older C request, but since it is +a single request, it might be more efficient to use. + +Example: load F into C<$passwd>. + + my $passwd; + aio_slurp "/etc/passwd", 0, 0, $passwd, sub { + $_[0] >= 0 + or die "/etc/passwd: $!\n"; + + printf "/etc/passwd is %d bytes long, and contains:\n", length $passwd; + print $passwd; + }; + IO::AIO::flush; + + =item aio_load $pathname, $data, $callback->($status) This is a composite request that tries to fully load the given file into memory. Status is the same as with aio_read. +Using C might be more efficient, as it is a single request. + =cut sub aio_load($$;$) { @@ -960,6 +939,8 @@ destination) from C<$srcpath> to C<$dstpath> and call the callback with a status of C<0> (ok) or C<-1> (error, see C<$!>). +Existing destination files will be truncated. + This is a composite request that creates the destination file with mode 0200 and copies the contents of the source file into it using C, followed by restoring atime, mtime, access mode and @@ -1078,7 +1059,7 @@ names, directories you can recurse into (directories), and ones you cannot recurse into (everything else, including symlinks to directories). -C is a composite request that creates of many sub requests_ +C is a composite request that generates many sub requests. C<$maxreq> specifies the maximum number of outstanding aio requests that this function generates. If it is C<< <= 0 >>, then a suitable default will be chosen (currently 4). @@ -1152,13 +1133,69 @@ return $grp->result () if $_[0]; my $now = time; my $hash1 = join ":", (stat _)[0,1,3,7,9]; + my $rdxflags = READDIR_DIRS_FIRST; + + if ((stat _)[3] < 2) { + # at least one non-POSIX filesystem exists + # that returns useful DT_type values: btrfs, + # so optimise for this here by requesting dents + $rdxflags |= READDIR_DENTS; + } # read the directory entries aioreq_pri $pri; - add $grp aio_readdirx $wd, READDIR_DIRS_FIRST, sub { - my $entries = shift + add $grp aio_readdirx $wd, $rdxflags, sub { + my ($entries, $flags) = @_ or return $grp->result (); + if ($rdxflags & READDIR_DENTS) { + # if we requested type values, see if we can use them directly. + + # if there were any DT_UNKNOWN entries then we assume we + # don't know. alternatively, we could assume that if we get + # one DT_DIR, then all directories are indeed marked with + # DT_DIR, but this seems not required for btrfs, and this + # is basically the "btrfs can't get it's act together" code + # branch. + unless ($flags & READDIR_FOUND_UNKNOWN) { + # now we have valid DT_ information for all entries, + # so use it as an optimisation without further stat's. + # they must also all be at the beginning of @$entries + # by now. + + my $dirs; + + if (@$entries) { + for (0 .. $#$entries) { + if ($entries->[$_][1] != DT_DIR) { + # splice out directories + $dirs = [splice @$entries, 0, $_]; + last; + } + } + + # if we didn't find any non-dir, then all entries are dirs + unless ($dirs) { + ($dirs, $entries) = ($entries, []); + } + } else { + # directory is empty, so there are no sbdirs + $dirs = []; + } + + # either splice'd the directories out or the dir was empty. + # convert dents to filenames + $_ = $_->[0] for @$dirs; + $_ = $_->[0] for @$entries; + + return $grp->result ($dirs, $entries); + } + + # cannot use, so return to our old ways + # by pretending we only scanned for names. + $_ = $_->[0] for @$entries; + } + # stat the dir another time aioreq_pri $pri; add $grp aio_stat $wd, sub { @@ -1273,7 +1310,8 @@ other processes), although if you are careful and know what you are doing, you still can. -The following constants are available (missing ones are, as usual C<0>): +The following constants are available and can be used for normal C +and C as well (missing ones are, as usual C<0>): C, @@ -1281,6 +1319,9 @@ C, C, C, C, C, C. +C, C, C, C, C and +C. + C, C, C, C, C. @@ -1428,11 +1469,14 @@ =item aio_mlockall $flags, $callback->($status) -Calls the C function with the given C<$flags> (a combination of -C and C). +Calls the C function with the given C<$flags> (a +combination of C, C and +C). On systems that do not implement C, this function returns C<-1> -and sets errno to C. +and sets errno to C. Similarly, flag combinations not supported +by the system result in a return value of C<-1> with errno being set to +C. Note that the corresponding C is synchronous and is documented under L. @@ -1481,10 +1525,11 @@ C, C or C. -At the time of this writing (Linux 3.2), this requets is unreliable unless +At the time of this writing (Linux 3.2), this request is unreliable unless C<$count> is C, as the kernel has all sorts of bugs preventing -it to return all extents of a range for files with large number of -extents. The code works around all these issues if C<$count> is undef. +it to return all extents of a range for files with a large number of +extents. The code (only) works around all these issues if C<$count> is +C. =item aio_group $callback->(...) @@ -1607,8 +1652,8 @@ nowhere at all), while the directory fd, if available on the system, will still point to the original directory. Most functions accepting a pathname will use the directory fd on newer systems, and the string on -older systems. Some functions (such as realpath) will always rely on the -string form of the pathname. +older systems. Some functions (such as C) will always rely on +the string form of the pathname. So this functionality is mainly useful to get some protection against C, to easily get an absolute path out of a relative path for future @@ -1826,6 +1871,7 @@ =back + =head2 SUPPORT FUNCTIONS =head3 EVENT PROCESSING AND EVENT LOOP INTEGRATION @@ -1900,6 +1946,16 @@ IO::AIO::poll_wait, IO::AIO::poll_cb while IO::AIO::nreqs; +This function can be useful at program aborts, to make sure outstanding +I/O has been done (C uses an C block which already calls +this function on normal exits), or when you are merely using C +for its more advanced functions, rather than for async I/O, e.g.: + + my ($dirs, $nondirs); + IO::AIO::aio_scandir "/tmp", 0, sub { ($dirs, $nondirs) = @_ }; + IO::AIO::flush; + # $dirs, $nondirs are now set + =item IO::AIO::max_poll_reqs $nreqs =item IO::AIO::max_poll_time $seconds @@ -1935,6 +1991,7 @@ =back + =head3 CONTROLLING THE NUMBER OF THREADS =over @@ -2010,7 +2067,7 @@ use an C together with a feed callback. Its main use is in scripts without an event loop - when you want to stat -a lot of files, you can write somehting like this: +a lot of files, you can write something like this: IO::AIO::max_outstanding 32; @@ -2031,6 +2088,7 @@ =back + =head3 STATISTICAL INFORMATION =over @@ -2057,6 +2115,101 @@ =back + +=head3 SUBSECOND STAT TIME ACCESS + +Both C/C and perl's C/C functions can +generally find access/modification and change times with subsecond time +accuracy of the system supports it, but perl's built-in functions only +return the integer part. + +The following functions return the timestamps of the most recent +stat with subsecond precision on most systems and work both after +C/C and perl's C/C calls. Their return +value is only meaningful after a successful C/C call, or +during/after a successful C/C callback. + +This is similar to the L C functions, but can return +full resolution without rounding and work with standard perl C, +alleviating the need to call the special C functions, which +do not act like their perl counterparts. + +On operating systems or file systems where subsecond time resolution is +not supported or could not be detected, a fractional part of C<0> is +returned, so it is always safe to call these functions. + +=over 4 + +=item $seconds = IO::AIO::st_atime, IO::AIO::st_mtime, IO::AIO::st_ctime, IO::AIO::st_btime + +Return the access, modication, change or birth time, respectively, +including fractional part. Due to the limited precision of floating point, +the accuracy on most platforms is only a bit better than milliseconds +for times around now - see the I function family, below, for full +accuracy. + +File birth time is only available when the OS and perl support it (on +FreeBSD and NetBSD at the time of this writing, although support is +adaptive, so if your OS/perl gains support, IO::AIO can take advantage of +it). On systems where it isn't available, C<0> is currently returned, but +this might change to C in a future version. + +=item ($atime, $mtime, $ctime, $btime, ...) = IO::AIO::st_xtime + +Returns access, modification, change and birth time all in one go, and +maybe more times in the future version. + +=item $nanoseconds = IO::AIO::st_atimensec, IO::AIO::st_mtimensec, IO::AIO::st_ctimensec, IO::AIO::st_btimensec + +Return the fractional access, modifcation, change or birth time, in nanoseconds, +as an integer in the range C<0> to C<999999999>. + +Note that no accessors are provided for access, modification and +change times - you need to get those from C if required (C and so on will I generally give you the correct +value). + +=item $seconds = IO::AIO::st_btimesec + +The (integral) seconds part of the file birth time, if available. + +=item ($atime, $mtime, $ctime, $btime, ...) = IO::AIO::st_xtimensec + +Like the functions above, but returns all four times in one go (and maybe +more in future versions). + +=item $counter = IO::AIO::st_gen + +Returns the generation counter (in practice this is just a random number) +of the file. This is only available on platforms which have this member in +their C (most BSDs at the time of this writing) and generally +only to the root usert. If unsupported, C<0> is returned, but this might +change to C in a future version. + +=back + +Example: print the high resolution modification time of F, using +C, and C. + + if (stat "/etc") { + printf "stat(/etc) mtime: %f\n", IO::AIO::st_mtime; + } + + IO::AIO::aio_stat "/etc", sub { + $_[0] + and return; + + printf "aio_stat(/etc) mtime: %d.%09d\n", (stat _)[9], IO::AIO::st_mtimensec; + }; + + IO::AIO::flush; + +Output of the awbove on my system, showing reduced and full accuracy: + + stat(/etc) mtime: 1534043702.020808 + aio_stat(/etc) mtime: 1534043702.020807792 + + =head3 MISCELLANEOUS FUNCTIONS IO::AIO implements some functions that are useful when you want to use @@ -2066,6 +2219,31 @@ =over 4 +=item $numfd = IO::AIO::get_fdlimit + +This function is I and subject to change. + +Tries to find the current file descriptor limit and returns it, or +C and sets C<$!> in case of an error. The limit is one larger than +the highest valid file descriptor number. + +=item IO::AIO::min_fdlimit [$numfd] + +This function is I and subject to change. + +Try to increase the current file descriptor limit(s) to at least C<$numfd> +by changing the soft or hard file descriptor resource limit. If C<$numfd> +is missing, it will try to set a very high limit, although this is not +recommended when you know the actual minimum that you require. + +If the limit cannot be raised enough, the function makes a best-effort +attempt to increase the limit as much as possible, using various +tricks, while still failing. You can query the resulting limit using +C. + +If an error occurs, returns C and sets C<$!>, otherwise returns +true. + =item IO::AIO::sendfile $ofh, $ifh, $offset, $count Calls the C function, which is like C, @@ -2181,6 +2359,34 @@ Removes a previous mmap and undefines the C<$scalar>. +=item IO::AIO::mremap $scalar, $new_length, $flags = MREMAP_MAYMOVE[, $new_address = 0] + +Calls the Linux-specific mremap(2) system call. The C<$scalar> must have +been mapped by C, and C<$flags> must currently either be +C<0> or C. + +Returns true if successful, and false otherwise. If the underlying mmapped +region has changed address, then the true value has the numerical value +C<1>, otherwise it has the numerical value C<0>: + + my $success = IO::AIO::mremap $mmapped, 8192, IO::AIO::MREMAP_MAYMOVE + or die "mremap: $!"; + + if ($success*1) { + warn "scalar has chanegd address in memory\n"; + } + +C and the C<$new_address> argument are currently +implemented, but not supported and might go away in a future version. + +On systems where this call is not supported or is not emulated, this call +returns falls and sets C<$!> to C. + +=item IO::AIO::mlockall $flags + +Calls the C function, which is like C, +but is blocking. + =item IO::AIO::munlock $scalar, $offset = 0, $length = undef Calls the C function, undoing the effects of a previous @@ -2240,6 +2446,110 @@ time of this writing, C, C and C (Linux 3.4, for packet-based pipes) were supported. +Example: create a pipe race-free w.r.t. threads and fork: + + my ($rfh, $wfh) = IO::AIO::pipe2 IO::AIO::O_CLOEXEC + or die "pipe2: $!\n"; + +=item $fh = IO::AIO::memfd_create $pathname[, $flags] + +This is a direct interface to the Linux L system +call. The (unhelpful) default for C<$flags> is C<0>, but your default +should be C. + +On success, the new memfd filehandle is returned, otherwise returns +C. If the memfd_create syscall is missing, fails with C. + +Please refer to L for more info on this call. + +The following C<$flags> values are available: C, +C and C. + +Example: create a new memfd. + + my $fh = IO::AIO::memfd_create "somenameforprocfd", IO::AIO::MFD_CLOEXEC + or die "m,emfd_create: $!\n"; +=item $fh = IO::AIO::eventfd [$initval, [$flags]] + +This is a direct interface to the Linux L system call. The +(unhelpful) defaults for C<$initval> and C<$flags> are C<0> for both. + +On success, the new eventfd filehandle is returned, otherwise returns +C. If the eventfd syscall is missing, fails with C. + +Please refer to L for more info on this call. + +The following symbol flag values are available: C, +C and C (Linux 2.6.30). + +Example: create a new eventfd filehandle: + + $fh = IO::AIO::eventfd 0, IO::AIO::EFD_CLOEXEC + or die "eventfd: $!\n"; + +=item $fh = IO::AIO::timerfd_create $clockid[, $flags] + +This is a direct interface to the Linux L system +call. The (unhelpful) default for C<$flags> is C<0>, but your default +should be C. + +On success, the new timerfd filehandle is returned, otherwise returns +C. If the timerfd_create syscall is missing, fails with C. + +Please refer to L for more info on this call. + +The following C<$clockid> values are +available: C, C +C (Linux 3.15) +C (Linux 3.11) and +C (Linux 3.11). + +The following C<$flags> values are available (Linux +2.6.27): C and C. + +Example: create a new timerfd and set it to one-second repeated alarms, +then wait for two alarms: + + my $fh = IO::AIO::timerfd_create IO::AIO::CLOCK_BOOTTIME, IO::AIO::TFD_CLOEXEC + or die "timerfd_create: $!\n"; + + defined IO::AIO::timerfd_settime $fh, 0, 1, 1 + or die "timerfd_settime: $!\n"; + + for (1..2) { + 8 == sysread $fh, my $buf, 8 + or die "timerfd read failure\n"; + + printf "number of expirations (likely 1): %d\n", + unpack "Q", $buf; + } + +=item ($cur_interval, $cur_value) = IO::AIO::timerfd_settime $fh, $flags, $new_interval, $nbw_value + +This is a direct interface to the Linux L system +call. Please refer to its manpage for more info on this call. + +The new itimerspec is specified using two (possibly fractional) second +values, C<$new_interval> and C<$new_value>). + +On success, the current interval and value are returned (as per +C). On failure, the empty list is returned. + +The following C<$flags> values are +available: C and +C. + +See C for a full example. + +=item ($cur_interval, $cur_value) = IO::AIO::timerfd_gettime $fh + +This is a direct interface to the Linux L system +call. Please refer to its manpage for more info on this call. + +On success, returns the current values of interval and value for the given +timerfd (as potentially fractional second values). On failure, the empty +list is returned. + =back =cut @@ -2314,6 +2624,15 @@ =back +=head2 LINUX-SPECIFIC CALLS + +When a call is documented as "linux-specific" then this means it +originated on GNU/Linux. C will usually try to autodetect the +availability and compatibility of such calls regardless of the platform +it is compiled on, so platforms such as FreeBSD which often implement +these calls will work. When in doubt, call them and see if they fail wth +C. + =head2 MEMORY USAGE Per-request usage: @@ -2335,7 +2654,18 @@ =head1 KNOWN BUGS -Known bugs will be fixed in the next release. +Known bugs will be fixed in the next release :) + +=head1 KNOWN ISSUES + +Calls that try to "import" foreign memory areas (such as C +or C) do not work with generic lvalues, such as +non-created hash slots or other scalars I didn't think of. It's best to +avoid such and either use scalar variables or making sure that the scalar +exists (e.g. by storing C) and isn't "funny" (e.g. tied). + +I am not sure anything can be done about this, so this is considered a +known issue, rather than a bug. =head1 SEE ALSO